1. 程式人生 > >ArrayList的序列化與擴容

ArrayList的序列化與擴容

       ArrayList的底層實現時陣列,與普通的陣列相比,ArrayList能實現容量的動態增長。在ArrayList中最重要的屬性是: elementData和size。elementData是Object[]的陣列,size是陣列中實際元素的大小。

(一)序列化

       可以看到elementData被transient修飾了。transient用來說明elementData並不參與序列化的過程,而ArrayList是實現Serializable介面的,具體的序列化實現在writeObject()方法中,序列化的內容只取實際元素的元素(即size實際大小的元素)以減少io的損耗。

(二)擴容

(1)什麼時候擴容?        以向ArrayList中新增元素的add()方法為例:

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

private void ensureCapacityInternal(int minCapacity) {
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
    }

    ensureExplicitCapacity(minCapacity);
}

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

    // overflow-conscious code
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}

       可以看到當minCapacity大於elementData的容量時,便開始擴容,而minCapacity是由size+1和DEFAULT_CAPACITY(預設10) 的大者決定的。

(2)擴多大的容?

       先看下擴容的程式碼:

private void grow(int minCapacity) {
    // overflow-conscious code
    int oldCapacity = elementData.length;
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;  //(tag 1)
    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);
}

private static int hugeCapacity(int minCapacity) {
    if (minCapacity < 0) // overflow
        throw new OutOfMemoryError();
    return (minCapacity > MAX_ARRAY_SIZE) ?
        Integer.MAX_VALUE :
        MAX_ARRAY_SIZE;
}

       在上面的程式碼中,在tag 1之前newCapacity大小獲取的思路是取minCapacity和oldCapacity擴大1.5倍(oldCapacity >> 1位移運算,計算的結果是oldCapacity的一半)的較大者。之後當newCapacity大於 MAX_ARRAY_SIZE時呼叫hugeCapacity()計算newCapacity新的值。其中MAX_ARRAY_SIZE=Integer.MAX_VALUE - 8。在官方的說明中,減8是因為一些虛擬機器保留頭資訊,減8可以減少出錯的概率。在hugeCapacity中可以看到 return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE :MAX_ARRAY_SIZE;,因此陣列擴容後最大值依然為Integer.MAX_VALUE。