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

Java ArrayList擴容機制

  • ArrayList中維護了一個Object型別的資料,elementData
  •  transient Object[] elementData;
    
  •  //transient表示該物件不會被序列化(序列化——把Java物件轉換為位元組序列的過程)
    
  •   當建立ArrayList物件時,如果使用的是無參構造器,則初始elementData容量為0,第一次新增,則擴容為10,如果需要再次擴容,則擴容為elementData為1.5倍
    
  •  如果使用的是指定大小的構造器,則初始化elementData容量為指定大小,如果需要擴容,則直接擴容為elementData為1.5倍
    

通過下列示例來說明該機制

package gather.collection.list;

import java.util.ArrayList;
@SuppressWarnings({"all"})//抑制警告
/**
 * @Author Blueshadow
 * @Date 2021/7/20 11:00
 * @Version 1.0
 */
public class list {
    public static void main(String[] args) {
        ArrayList list = new ArrayList();//elementData陣列初始大小為0
        for (int i = 0; i < 10 ; i++) {
            list.add(i);
        }

        list.add(100);
        list.add(200);
        list.add(null);
        for (Object object : list) {
            System.out.println(object);
        }
    }
}

底層原始碼說明

第一次初始化,建立了一個名為elementData的Object型別的陣列,該陣列可以存放多種型別的資料,主要是通過包裝類來實現。

public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    //private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};//建立Object型別陣列
    //建立了一個空陣列,並將陣列命名為 elemenrData
    }

下一步:在執行list.add(1)時,會先進性判斷,是否需要擴容,然後再執行賦值操作。

public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // 判斷Increments modCount!!
        elementData[size++] = e;//賦值操作
        return true;
    }

下一步:判斷是空,則給陣列賦予一個最小容量,第一次add,最小容量為minCapacity。

private void ensureCapacityInternal(int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {//先確定elementData是否是一個空陣列:
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);//先確定最小容量minCapacity(第一次擴容為10)
        }
        ensureExplicitCapacity(minCapacity);//真正確定是否擴容
    }

下一步:進行底層的擴容。

private void ensureExplicitCapacity(int minCapacity) {
        modCount++;//記錄當前集合被修改的次數

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)//如果elementDara容量不夠,就呼叫grow方法進行擴容
            grow(minCapacity);//進行底層的擴容
    }

第一次擴容最後一步:底層按照1.5倍進行擴容


 private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;//第一次oldCapacity=0
        int newCapacity = oldCapacity + (oldCapacity >> 1);//原先陣列大小+原先陣列大小/2
        if (newCapacity - minCapacity < 0)
            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={},使用該方法將newCapacity賦值給elementData
    }