ArrayList的初始容量現(xiàn)在為0,不再是10了

前言

一直記得ArrayList的初始容量大小是10,今天再次看ArrayList的源碼(版本:Jdk 7u80)時(shí)發(fā)現(xiàn)在構(gòu)造函數(shù)的注釋上寫著初始化容量是10,但是構(gòu)造函數(shù)中卻沒有指定初始容量,僅僅初始化了一個(gè)空的數(shù)組。應(yīng)該是不知道在哪個(gè)版本中已經(jīng)修改了,我卻還記著之前從別人口里得來的一句話:初始容量是10。實(shí)際上初始容量已經(jīng)是0了,寫出來分享下,有錯(cuò)的地方煩請(qǐng)指出來,說的不一定對(duì)。

測(cè)試

寫了下代碼來測(cè)試下,ArrayList中沒有直接獲取capacity的方法,只能通過反射獲取elementData數(shù)組的size來間接獲取到capacity。代碼如下:

public class ArrayListCapacityTest {

    public static void main(String[] args) {
        ArrayList arrayList = new ArrayList();
        System.out.println("capacity: " + getCapacity(arrayList) + " size: " + arrayList.size());

        arrayList.add("test");
        System.out.println("capacity: " + getCapacity(arrayList) + " size: " + arrayList.size());

        arrayList = new ArrayList(11);
        System.out.println("capacity: " + getCapacity(arrayList) + " size: " + arrayList.size());
        }

    public static int getCapacity(ArrayList arrayList) {
        try {
            Field elementDataField = ArrayList.class.getDeclaredField("elementData");
            elementDataField.setAccessible(true);
            return ((Object[]) elementDataField.get(arrayList)).length;
        } catch (NoSuchFieldException | IllegalAccessException e) {
            e.printStackTrace();
            return -1;
        }
    }
}

結(jié)果如下:

capacity: 0 size: 0
capacity: 10 size: 1
capacity: 11 size: 0

分析

上面結(jié)果也可以看出來,確實(shí)是初始容量為0了。接著看下ArrayList的源碼(下面所有源碼版本為Jdk 7u80):

 /**
  * Constructs an empty list with an initial capacity of ten.
 */
public ArrayList() {
    super();
    this.elementData = EMPTY_ELEMENTDATA;
}

源碼中這注釋確實(shí)很誤導(dǎo)人,構(gòu)造函數(shù)中沒有初始化大小。但是現(xiàn)在這樣有個(gè)問題,數(shù)組大小為0, 我怎么添加元素進(jìn)去?應(yīng)該就是在add的時(shí)候初始化,繼續(xù)跟進(jìn)add方法的源碼:

public boolean add(E e) {
    // 如果剛初始化ArrayList,size肯定是0
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    elementData[size++] = e;
    return true;
}

add方法中第一步先確保容量夠用,這里面有可能就是初始化容量的方法,繼續(xù)跟進(jìn)ensureCapacityInternal的源碼:

private void ensureCapacityInternal(int minCapacity) {
    // 由上一步知道m(xù)inCapacity為1
    // 這里if的條件也一定為true
    if (elementData == EMPTY_ELEMENTDATA) {
        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    // 經(jīng)過上一步之后,minCapacity就等于DEFAULT_CAPACITY,即10。
    ensureExplicitCapacity(minCapacity);
}

繼續(xù)跟進(jìn)ensureExplicitCapacity源碼:

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

    // overflow-conscious code
    // minCapacity此時(shí)為10,if條件成立
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}

繼續(xù)跟進(jìn)grow源碼:

private void grow(int minCapacity) {
    // overflow-conscious code
    // oldCapacity = 0
    int oldCapacity = elementData.length;
    // newCapacity = 0
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    if (newCapacity - minCapacity < 0)
        // newCapacity由上層傳來為10
        newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    // minCapacity is usually close to size, so this is a win:
    // 這里就是數(shù)組初始化為10的地方了
    elementData = Arrays.copyOf(elementData, newCapacity);
}

源碼跟到這里就算完了,確實(shí)是在add的時(shí)候初始化容量為10。

結(jié)論

ArrayList的初始化容量已經(jīng)變了,不再是以前的10了,而是初始化為0,等到第一次add的時(shí)候再初始化為10。

做這樣的改動(dòng),就是延遲初始化ArrayList的實(shí)際容量,應(yīng)該是考慮到空間的問題,如果一開始就初始化為10,這個(gè)大小為10的數(shù)組中就全部是存的null,如果數(shù)量多了,這個(gè)也是很大的空間。應(yīng)該是這樣的原因吧。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 越過時(shí)空的長(zhǎng)河,我悄然而至 來到你的世界,只為把你遇見 于此,我是一個(gè)孤獨(dú)的陌生人 丟了前世的記憶,忘掉伊人容顏 ...
    閑狐兔閱讀 291評(píng)論 0 0
  • ?——海維斯黑發(fā)露?大優(yōu)勢(shì)值得信賴[強(qiáng)][強(qiáng)] QQ:826806759
    vV素顏閱讀 196評(píng)論 0 1
  • 這個(gè) 給我的感覺就像是 PPT 播放一樣。這里找了一些資料,學(xué)習(xí)視頻合成方面的知識(shí)。 一:圖片和視頻的合成: @i...
    icc_tips閱讀 8,278評(píng)論 10 25
  • 使用nvm利器,管理node版本 command not found nvm安裝成功后,但命令不可用 mac的終端...
    奔跑的兔子_閱讀 274評(píng)論 0 0