1. 程式人生 > 實用技巧 >ArrayList原始碼分析

ArrayList原始碼分析

ArrayList原始碼分析

一隻java小白

最近學到集合,於是想分析一下ArrayList的原始碼。

  • 預設長度是多少?

    通過翻閱原始碼,發現是10

    //預設長度是10  
    private static final int DEFAULT_CAPACITY = 10;
    //無引數構造器,這裡只初始化了一個數組(ArrayList通過陣列來儲存資料)。
    public ArrayList() {
      this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }
    //找到原始碼,發現是一個空的陣列,那麼長度是咋變成10的呢?
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
    
  • 我此時發現了一句註釋:

    * Any empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
    * will be expanded to DEFAULT_CAPACITY when the first element is added.
    

    所以該陣列的長度是在新增第一個資料時變成10的!!!下面來做個假設,於是我跟蹤add()方法

 public boolean add(E e) {
     modCount++;
     //引數解釋:
     //    e:形參,elementData:存放的資料,size:此時存放多個數據(預設是0)
     
     add(e, elementData, size);
     return true;
 }
//繼續跟蹤,發現是在這個if語句中進行了擴容
 private void add(E e, Object[] elementData, int s) {
    //陣列長度也是0,條件為true
     if (s == elementData.length)
         elementData = grow();
     elementData[s] = e;
     size = s + 1;
 }

private Object[] grow() {
    //實參變為1
    return grow(size + 1);
}
private Object[] grow(int minCapacity) {
    int oldCapacity = elementData.length;
    //先不分析,這是建立ArrayList物件時指定長度或者第一次擴容之後再次擴容,才進到這裡
	//
    if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        //擴容為之前的1.5倍取整
        int newCapacity = ArraysSupport.newLength(oldCapacity,
                                                  minCapacity - oldCapacity, /* minimum growth */
                                                  oldCapacity >> 1           /* preferred growth */);
        // public static int newLength(int oldLength, int minGrowth, int prefGrowth) {
        // assert oldLength >= 0
        // assert minGrowth > 0

        //   int newLength = Math.max(minGrowth, prefGrowth) + oldLength;
        // if (newLength - MAX_ARRAY_LENGTH <= 0) {
        //   return newLength;
        // }
        //	return hugeLength(oldLength, minGrowth);
        //}
        //賦值給新創建出的陣列,舊的陣列自動回收!!!
        return elementData = Arrays.copyOf(elementData, newCapacity);
    } else {
        
        //跳到這裡,都明白了,在10和size中取最大值,進行第一次擴容
        return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];
    }
}

  • Arrays.copyOf方法深究

    //靜態泛型方法
    public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
        @SuppressWarnings("unchecked")
        //判斷newType是否是Object陣列
        T[] copy = ((Object)newType == (Object)Object[].class)
            ? (T[]) new Object[newLength]
            : (T[]) Array.newInstance(newType.getComponentType(), newLength);
        
        //重點,複製陣列
        //原陣列:original,目標陣列:copy
       //從original下標0開始將資料複製到copy陣列中,第一個資料放在下標0中,長度為 Math.min(original.length, newLength)
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
        return copy;
    }
    

有必要總結下泛型:),繼續努力!!!