【數組】- ArrayList自動擴容機制

注意:數組

不一樣的JDK版本的擴容機制可能有差別 實驗環境:JDK1.8函數

擴容機制性能

當向ArrayList中添加元素的時候,ArrayList若是要知足新元素的存儲超過ArrayList存儲新元素前的存儲能力,ArrayList會加強自身的存儲能力,已達到存儲新元素的要求this

ArrayList:本質經過內部維護的數組對象進行數據存儲code

①:分析ArrayList的add(E)方法對象

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

分析:add方法首先經過ensureCapacityInternal()方法確保當前ArrayList維護的數組具備存儲新元素的能力,通過處理以後將元素存儲在數組elementData的尾部 elementData:ArrayList真正用於存儲元素的數組ci

②:分析ensureCapacityInternal方法element

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

分析:ensureCapacityInternal判斷ArrayList默認的元素存儲數據是否爲空,爲空則設置最小要求的存儲能力爲必要存儲的元素和默認存儲元素個數的兩個數據之間的最大值,而後調用ensureExplicitCapacity方法實現這種最低要求的存儲能力rem

注意:ArrayList的存儲空間並非須要一個建立一個,而是分階段性的建立,通常會預留存儲空間。 例如,若是ArrayList須要存儲10個元素,剛好ArrayList只能存儲6個元素,剩餘4個元素沒法存儲,ArrayList可能會一次性擴展10個元素,這種ArrayList就有20個元素的存儲能力,在存儲能力範圍內,下次再存放元素,就不須要再次擴容工作流

③:分析ensureExplicitCapacity方法:

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

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

分析:若是最低要求的存儲能力>ArrayList已有的存儲能力,這就表示ArrayList的存儲能力不足,所以須要調用 grow();方法進行擴容 ④:分析grow()方法

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);
    }

分析:當ArrayList擴容的時候,首先會設置新的存儲能力爲原來的1.5倍

int newCapacity = oldCapacity + (oldCapacity >> 1);

若是擴容以後仍是不能知足要求則MAX_ARRAY_SIZE比較,求取最大值, 若是MAX_ARRAY_SIZE大小的能力仍是不能知足則經過hugeCapacity()方法獲取ArrayList能容許的最大值:

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

從hugeCapacity方法看出,ArrayList最大的存儲能力:存儲元素的個數爲整型的範圍。 肯定ArrayList擴容以後最新的可存儲元素個數時,調用 elementData = Arrays.copyOf(elementData, newCapacity); 實現elementData數組的擴容,整個流程就是ArrayList的自動擴容機制工做流程

擴展: ArrayList的自動擴容機制底層藉助於System實現

public static native void arraycopy
  (Object src,  int  srcPos,
   Object dest, int destPos,
   int length);

arraycopy標識爲native意味JDK的本地庫,不可避免的會進行IO操做,若是頻繁的對ArrayList進行擴容,絕不疑問會下降ArrayList的使用性能,所以當咱們肯定添加元素的個數的時候,咱們能夠事先知道並指定ArrayList的可存儲元素的個數,這樣當咱們向ArrayList中加入元素的時候,就能夠避免ArrayList的自動擴容,從而提升ArrayList的性能

ArrayList含參構造函數:初始化時指定存儲元素的能力:

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);                                               
        }
    }
相關文章
相關標籤/搜索