1. 程式人生 > >Java基礎複習筆記-----使用ArrayList時設定初始容量的重要性

Java基礎複習筆記-----使用ArrayList時設定初始容量的重要性

ArrayList是Java中比較常用的一個類,它底層是基於陣列實現,非執行緒安全,可快速隨機訪問List中的元素。ArrayList具有動態擴容的機制,每次在新增元素時,都會判斷容量是否夠用,如果不夠用,則需要擴容。在JDK1.8中,ArrayList的初始容量為0,第一次新增元素時,會將擴容程式碼如下:


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

其中:

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

容量被擴充為原容量的1.5倍,oldCapacity>>1,右移一位,即:oldCapacity除以2

elementData = Arrays.copyOf(elementData, newCapacity);

用Arrays的copyOf方法拷貝原陣列內容,並設定新的長度。

可以看到ArrayList擴容需要做一次陣列拷貝,如果是反覆擴容,肯定會對程式的執行效率產生影響。所以在初始化ArrayList的時候,儘量設定初始化容量,避免其擴容。

測試程式碼:


final int count = 20 * 500000;
        List<Integer> list = new ArrayList<>();
        long begin = System.currentTimeMillis();
        for(int i = 0; i < count ; i++) {
            list.add(i);
        }
        System.out.println("沒有設定ArrayList初始容量: " + (System.currentTimeMillis() - begin) + " ms"); 
        list = new ArrayList<>(count);
        begin = System.currentTimeMillis();
        for(int i = 0; i < count ; i++) {
            list.add(i);
        }
        System.out.println("設定了ArrayList初始容量: " + (System.currentTimeMillis() - begin) + " ms");

執行結果:

沒有設定ArrayList初始容量: 3983 ms

設定了ArrayList初始容量: 187 ms

需要的容量越多越能體現初始化時定義容量的優越性。