1. 程式人生 > 其它 >ArrayList的擴容機制

ArrayList的擴容機制

ArrayList擴容機制

從原始碼分析

  ArrayList是List介面的實現類,它是支援根據需要而動態增長的陣列。java中標準陣列是定長的,在陣列被建立之後,它們不能被加長或縮短。這就意味著在建立陣列時需要知道陣列的所需長度,但有時我們需要動態程式中獲取陣列長度。ArrayList就是為此而生的。

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

  • ArrayList擴容發生在呼叫add()方法的時候,下面是add()方法的原始碼:
  • 存放元素的陣列:elementData
    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)獲取:

  • 預設容量大小:DEFAULT_CAPACITY=10;

    private static int calculateCapacity(Object[] elementData, int minCapacity) {
        //如果傳入的是個空陣列則最小容量取預設容量與minCapacity之間的最大值
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            return Math.max(DEFAULT_CAPACITY, minCapacity);//(10,0)
        }
        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後例項化,並將原有陣列內容複製到新陣列中去。