1. 程式人生 > >ArrayList的原始碼分析(基於jdk1.8)

ArrayList的原始碼分析(基於jdk1.8)

1.初始化

transient Object[] elementData;  //實際儲存元素的陣列

private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

public ArrayList() {
    //初始化為一個預設的空陣列
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

 

2. 新增元素

private static final int DEFAULT_CAPACITY = 10;//預設容量

public
boolean add(E e) { //確保當前陣列的容量是夠得 ensureCapacityInternal(size + 1); // Increments modCount!! //將新元素新增到[size++]的位置 elementData[size++] = e; return true; }
private void ensureCapacityInternal(int minCapacity) { //如果是第一次新增 if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {   //
擴容為預設容量大小:10   minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } //每一次新增都要判斷是否需要擴容 ensureExplicitCapacity(minCapacity); }

 

3.擴容

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

    // 如果需要擴容
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}

private void grow(int minCapacity) { // 先獲取當前陣列的容量 int oldCapacity = elementData.length; //新容量為當前容量 + 當前容量的一半 int newCapacity = oldCapacity + (oldCapacity >> 1); if (newCapacity - minCapacity < 0) newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); // 拷貝原陣列中的元素至新陣列,並返回新陣列的引用 elementData = Arrays.copyOf(elementData, newCapacity); }

 

4.結論

  ArrayList物理結構是陣列,決定了它的儲存特點是:需要開闢連續的儲存空間來儲存元素,當儲存容量不夠時,需要擴容,增加容量為原來的1.5倍。類似的,Vector的物理結構也是陣列,當儲存容量不夠時,需要擴容為原來的2倍。那麼是1.5倍好呢?還是2倍好呢?1.5倍使得陣列空間使用率提高了,但是這也增加了擴容的頻率。所以,建議大家在選擇動態陣列時,如果對要儲存的元素個數有一個預估時,那麼可以在建立ArrayList時,就使用ArrayList(int initialCapacity) 構造器,避免反覆擴容。