jdk 1.8 Arraylist自動擴容
以無參構造為例
第一步:呼叫add方法新增元素
public boolean add(E e) { ensureCapacityInternal(size + 1); // 新增元素前先呼叫ensureCapacityInternal方法 elementData[size++] = e;//新增物件時,size+1 return true; }
第二步:呼叫ensureCapacityInternal方法,設定好minCapacity的值
private void ensureCapacityInternal(int minCapacity) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { //判斷是否為空陣列 minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } ensureExplicitCapacity(minCapacity); }
當空陣列新增第1個元素時,minCapacity=1,呼叫max()方法取出DEFAULT_CAPACITY和minCapacity的最大值 ,minCapacity變為DEFAULT_CAPACITY(預設大小10),呼叫ensureExplicitCapacity方法。
當新增第2個元素時,直接呼叫ensureExplicitCapacity方法。
第三步:呼叫ensureExplicitCapacity方法修改修改次數,並判斷是否需要擴容
private void ensureExplicitCapacity(int minCapacity) { modCount++;//修改次數加1 // overflow-conscious code if (minCapacity - elementData.length > 0) grow(minCapacity);//呼叫擴容方法 }
當新增第1個元素時,此時的elementData.length=1(為空列表),minCapacity=10,所以minCapacity>elementData.length,會進入grow(minCapacity)方法(此時minCapacity=10)。
當新增第2個元素時,此時的minCapacity=2,此時elementData.length(即是容量)在新增第一個元素後擴容成10了,所以minCapacity<elementData.length,不會進入grow(minCapacity)方法,陣列容量仍為10不變
所以當新增第3、4···到第10個元素時,依然不會執行grow方法,陣列容量都為10。
當新增到第11個元素時,(minCapacity=11)>(elementData.length=10),所以進入grow(minCapacity)方法進行擴容。
第四步:呼叫grow方法進行擴容
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; //通過位運算右移一位,相當於除以2,運算速度快,新容量擴大到原容量的1.5倍 int newCapacity = oldCapacity + (oldCapacity >> 1); if (newCapacity - minCapacity < 0) //從minCapacity和newCapacity種取出一個較大值作為擴容後新陣列的容量 //這個if判斷主要是針對新增第一個元素時使用,1.5倍的oldCapacity 還是為0,所以newCapacity為最小容量10 newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0) //如果新容量大於陣列的最大size,進入hugeCapacity方法 newCapacity = hugeCapacity(minCapacity); // minCapacity is usually close to size, so this is a win: //最後將原來的陣列和新的容量大小傳入到copyOf方法中複製(先設定一個新容量大小的陣列,把原資料放入其中即可) elementData = Arrays.copyOf(elementData, newCapacity); }
當add第1個元素時,oldCapacity為0,第一個if成立,newCapacity=minCapacity=10;但是第二個if不成立,則不會進入hugeCapacity方法,陣列容量為10,add方法中return true,size增為1。
當add第11個元素進入grow方法時,newCapacity為15,比minCapacity(為11)大,第一個if判斷不成立。新容量沒有大於陣列最大size,不會進入hugeCapacity方法。陣列容量擴為15,add方法中return true,size增為11。
第五步:如果新容量大於MAX_ARRAY_SIZE,進入hugeCapacity方法
private static int hugeCapacity(int minCapacity) { if (minCapacity < 0) // overflow throw new OutOfMemoryError(); return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; }