ArrayList的擴容機制


  ArrayList是List接口的實現類,它是支持根據需要而動態增長的數組。java中標准數組是定長的,在數組被創建之后,它們不能被加長或縮短。這就意味着在創建數組時需要知道數組的所需長度,但有時我們需要動態程序中獲取數組長度。ArrayList就是為此而生的。

  因此,了解它的擴容機制對使用它尤為重要。

  ArrayList擴容發生在add()方法調用的時候,下面是add()方法的源碼:

 

    public boolean add(E e) {
       //擴容
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }

  根據意思可以看出ensureCapacityInternal()是用來擴容的,形參為最小擴容量,進入此方法后:

private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}

   通過方法calculateCapacity(elementData, minCapacity)獲取:

    private static int calculateCapacity(Object[] elementData, int minCapacity) {
        //如果傳入的是個空數組則最小容量取默認容量與minCapacity之間的最大值
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        return minCapacity;
    }

   ensureExplicitCapacity方法可以判斷是否需要擴容:

 private void ensureExplicitCapacity(int minCapacity) {
          modCount++;
 
          // 如果最小需要空間比elementData的內存空間要大,則需要擴容
          if (minCapacity - elementData.length > 0)
              //擴容
              grow(minCapacity);
      }

   接下來重點來了,ArrayList擴容的關鍵方法grow():

  private void grow(int minCapacity) {
          // 獲取到ArrayList中elementData數組的內存空間長度
          int oldCapacity = elementData.length;
         // 擴容至原來的1.5倍
         int newCapacity = oldCapacity + (oldCapacity >> 1);
         // 再判斷一下新數組的容量夠不夠,夠了就直接使用這個長度創建新數組,
          // 不夠就將數組長度設置為需要的長度
         if (newCapacity - minCapacity < 0)
             newCapacity = minCapacity;
         //若預設值大於默認的最大值檢查是否溢出
         if (newCapacity - MAX_ARRAY_SIZE > 0)
             newCapacity = hugeCapacity(minCapacity);
         // 調用Arrays.copyOf方法將elementData數組指向新的內存空間時newCapacity的連續空間
         // 並將elementData的數據復制到新的內存空間
         elementData = Arrays.copyOf(elementData, newCapacity);
     }

 從此方法中我們可以清晰的看出其實ArrayList擴容的本質就是計算出新的擴容數組的size后實例化,並將原有數組內容復制到新數組中去。

到此擴容就基本完成了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM