天天看點

ArrayList 是怎麼實作可變長度的,Capacity容量

都知道ArrayList是基于數組的,那它是怎麼實作可變的呢?

建立ArrayList對象時,ArrayList有個帶參數的構造函數,那個參數的意思就代表着ArrayList長度,預設情況是10。當資料多了,ArrayList容不下時,這時ArrayList會增加長度,newLength = oldLength + oldLength/2;如果初始值是10,那麼依次是15,22,33,49,73......,長度是增加了,那是怎樣實作的呢?當資料容不下時,ArrayList會再建立一個更大的數組,數組長度為之前所說的那樣,然後将之前的資料拷貝到新數組中。這就是ArrayList基于數組實作的可變長度原理。

下面詳細解釋下:

1、代碼如下

ArrayList 是怎麼實作可變長度的,Capacity容量
ArrayList 是怎麼實作可變長度的,Capacity容量

ArrayList初始化時沒有設定容量大小,随後給他添加10個字元串,size變為10;當10個字元串添加完之後,繼續添加,這時ArrayList容量增加到15,size變為11。如果當ArrayList容量又滿了時,這時ArrayList容量增加到22,以此類推(10,15,22,33,49......),newCapacity = oldCapacity+(oldCapacity/2),截圖如下:

ArrayList 是怎麼實作可變長度的,Capacity容量
ArrayList 是怎麼實作可變長度的,Capacity容量

2、如果ArrayList初始化時不給其設定容量大小,當調用add方法時,會給其預設配置設定10容量值。

ArrayList 是怎麼實作可變長度的,Capacity容量

3、ArrayList中add方法

/**
     * Appends the specified element to the end of this list.
     *
     * @param e element to be appended to this list
     * @return <tt>true</tt> (as specified by {@link Collection#add})
     */
    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }
           

添加操作,首先會調用 ensureCapacityInternal(size + 1),其作用為保證數組的容量始終夠用,其中 size是elementData數組中元組的個數,初始為0。

ArrayList中ensureCapacityInternal方法

private void ensureCapacityInternal(int minCapacity) {
        if (elementData == 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);
    }
           

在ensureCapacityInternal()函數中,用if判斷, 如果數組沒有元素,給數組一個預設大小,會選擇執行個體化時的值與預設大小中較大值,然後調用ensure

Explicit

Capacity()。

ArrayList中grow方法

/**
     * Increases the capacity to ensure that it can hold at least the
     * number of elements specified by the minimum capacity argument.
     *
     * @param minCapacity the desired minimum capacity
     */
    private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        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);
    }
           
函數體中,modCount是數組發生size更改的次數。然後if判斷,                如果數組長度小于預設的容量10,則調用擴大數組大小的方法grow()。      
>>表示帶符号右移,如:int i=15; i>>2的結果是3,移出的部分将被抛棄。
轉為二進制的形式可能更好了解,0000 1111(15)右移2位的結果是0000 0011(3),0001 1010(18)右移3位的結果是0000 0011(3)。
           

10>>1 為5 

15>>1 為7

22>>1 為11 

4、從内部實作機制來講ArrayList是使用數組(Array)來控制集合中的對象。當你增加元素的時候,如果元素的數目超出了内部數組目前的長度,它需要擴充内部數組的長度,ArrayList是原來的50%,即newCapacity = oldCapacity+(oldCapacity/2)