1. 程式人生 > >ArrayList的add(E e)方法與擴容

ArrayList的add(E e)方法與擴容

ArrayList是Java開發中經常用到的集合類,它是List介面的實現類,具有很高的查詢效能,但不是執行緒安全的。本文主要講述了ArrayList的add(E e)方法及該方法中涉及到的容量擴容技術。

本文大綱

1.ArrayList底層資料結構

2.add(E e)方法流程概覽

3.add(E e)方法與擴容原始碼分析

說明:本文對ArrayList的原始碼分析是基於JDK8。

1.ArrayList底層資料結構

ArrayList的底層資料結構為一個Object陣列,對應到原始碼中是:

transient Object[] elementData; // non-private to simplify nested class access

2.add(E e)方法流程概覽

add(E e)方法的大致流程:

                       

3.add(E e)方法與擴容原始碼分析

接著再看一下原始碼:

public boolean add(E e) {
  // 確保陣列有足夠的空間來儲存物件e
  ensureCapacityInternal(size + 1); // Increments modCount!!
  // 將物件e存放到陣列的末尾
  elementData[size++] = e;
  
return true; }
ensureCapacityInternal方法主要是確保elementData陣列有足夠的空間來儲存待新增的元素:
// 引數minCapacity是add(E e)方法中呼叫ensureCapacityInternal方法時傳入的size + 1的值
private void ensureCapacityInternal(int minCapacity) {
    if (elementData == EMPTY_ELEMENTDATA) {
        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    ensureExplicitCapacity(minCapacity);
}

引數minCapacity是為了存放這個元素elementData陣列所需要的最小的大小。比如,現在一個數組中存放了10個元素,再次向該陣列存放一個元素時,那麼這個minCapacity的值就是size + 1,即10 + 1 = 11。

private void ensureExplicitCapacity(int minCapacity) {
    modCount++;

    // overflow-conscious code
    if (minCapacity - elementData.length > 0)
     // 存放新元素所需的最小容量大於elementData陣列的長度
        grow(minCapacity);
}

如果存放新元素所需的最小容量大於elementData陣列的長度,即當前陣列的容量不足,不能再存放新的元素,那麼將基於elementData陣列進行擴容。

private void grow(int minCapacity) {
    // overflow-conscious code
    int oldCapacity = elementData.length;
    int newCapacity = oldCapacity + (oldCapacity >> 1); // 計算新陣列的容量,新陣列的容量為原陣列容量的1.5倍數。>>是移位運算子,oldCapacity >> 1表示oldCapacity除以2
    if (newCapacity - minCapacity < 0) // 針對當建立的ArrayList的容量大小為1時能夠進行擴容(下面將詳細分析)
        newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    // minCapacity is usually close to size, so this is a win:
    elementData = Arrays.copyOf(elementData, newCapacity); // 進行陣列拷貝,並將新產生的陣列賦值給elementData
}

 

 當我們在new ArrayList的時候,如果指定ArrayList的容量大小為1(比如,new ArrayList<>(1)),再進行add(E e)操作,在執行程式碼int newCapacity = oldCapacity + (oldCapacity >> 1)時,newCapacity的值為1,newCapacity與oldCapacity的值都為1,這樣其實並沒有進行擴容。if (newCapacity - minCapacity < 0)就是為避免這種情況,當newCapacity(此例中為1)的值小於minCapacity(此例中為2)時,就把minCapacity的值賦給newCapacity。