1. 程式人生 > >java之ArrayList初始容量原始碼解析【jdk 1.8】

java之ArrayList初始容量原始碼解析【jdk 1.8】

ArrayList解析

繼承的類和實現的介面

public class ArrayList<E>extends AbstractList<E>implements List<E>, RandomAccess, Cloneable, Serializable

List 介面的大小可變陣列的實現。實現了所有可選列表操作,並允許包括 null 在內的所有元素。除了實現 List 介面外,此類還提供一些方法來操作內部用來儲存列表的陣列的大小。(此類大致上等同於 Vector 類,但此類是執行緒不安全的而vector是執行緒安全的。)

每個 ArrayList 例項都有一個容量。該容量是指用來儲存列表元素的陣列的大小。它總是至少等於列表的大小。隨著向 ArrayList 中不斷新增元素,其容量也自動增長。並未指定增長策略的細節,因為這不只是新增元素會帶來分攤固定時間開銷那樣簡單。

擴容公式:新容量 = 舊容量/2 + 舊容量(底層是通過移位操作,右移一位相當於除以2)

構造方法

ArrayList(): 這裡初始容量為 0,可能有人說是10,但別急,詳細可下面原始碼
              
ArrayList(Collection<? extends E> c) :構造一個包含指定 collection 的元素的列表,這些元素是按照該 collection
                                       的迭代器返回它們的順序排列的。 
                                       
ArrayList(int initialCapacity) :構造一個具有指定初始容量的空列表。 

原始碼 首先,定義一個elementData陣列,用來儲存ArrayList中的元素,從這個可以看出,ArrayList是底層是借組於陣列來實現的。

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

構造方法

 public ArrayList(int initialCapacity) {  //指定初始容量,這個好理解
        if (initialCapacity > 0) {
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }
  
    public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray(); //將容器collection轉化為陣列
        if ((size = elementData.length) != 0) {   //如果陣列非空
            // c.toArray might (incorrectly) not return Object[] (see 6260652)
            if (elementData.getClass() != Object[].class)   //
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            // replace with empty array.,用一個空陣列代替,這個空陣列是已經定義好的
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

另外一個就是這裡

   public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;  就是這裡,這是一個數組名,它的定義如下
    }

它的陣列是空的!

    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

鬱悶許久,來回看了幾次後,發現關於 transient Object[] elementData有這樣的一個介紹

The array buffer into which the elements of the ArrayList are stored.
     * The capacity of the ArrayList is the length of this array buffer. Any
     * empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
     * will be expanded to DEFAULT_CAPACITY when the first element is added.

transient Object[] elementData是一個儲存ArrayList元素的陣列緩衝區,ArrayList的容量是此陣列緩衝區的長度,在新增第一個元素時,將自動擴充套件為DEFAULT_CAPACITY,而DEFAULT_CAPACITY的申明是:

private static final int DEFAULT_CAPACITY = 10;

再看一個add方法

public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // 新增一個元素時,呼叫函式
        elementData[size++] = e;
        return true;
    }
  private void ensureCapacityInternal(int minCapacity) {
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }
  private static int calculateCapacity(Object[] elementData, int minCapacity) { 
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {//構造方法中已經初始化了,所以他們兩個相等
            return Math.max(DEFAULT_CAPACITY, minCapacity); //返回10
        }
        return minCapacity;
    }

因此,我覺得是在加入第一個元素後,容量才為10的,當然,這只是我的看法,我也無法保證一定是對的,如果哪位道友,覺得理解有誤的話,可以指出來,虛心學習,共同進步~