ArrayList擴容機制實探


ArrayList初始化

問題:執行以下代碼后,這個list的列表大小(size)和容量(capacity)分別是多大?
List<String> list = new ArrayList<>();

答案是:size = 0, capacity = 0,即我們使用無參構造方法創建ArrayList對象時,大小和容量都是為0。
那么如果我繼續執行:

        for(int i=0;i<100;i++) {
            list.add(String.valueOf(i));
        }

每次add之后,size和capacity 分別是多少?

答案是:

size = 1, capacity = 10
size = 2, capacity = 10
size = 3, capacity = 10
size = 4, capacity = 10
size = 5, capacity = 10
size = 6, capacity = 10
size = 7, capacity = 10
size = 8, capacity = 10
size = 9, capacity = 10
size = 10, capacity = 10
size = 11, capacity = 15
size = 12, capacity = 15
size = 13, capacity = 15
size = 14, capacity = 15
size = 15, capacity = 15
size = 16, capacity = 22
size = 17, capacity = 22
size = 18, capacity = 22
size = 19, capacity = 22
size = 20, capacity = 22
size = 21, capacity = 22
size = 22, capacity = 22
size = 23, capacity = 33
size = 24, capacity = 33
size = 25, capacity = 33
size = 26, capacity = 33
size = 27, capacity = 33
size = 28, capacity = 33
size = 29, capacity = 33
size = 30, capacity = 33
size = 31, capacity = 33
size = 32, capacity = 33
size = 33, capacity = 33
size = 34, capacity = 49
size = 35, capacity = 49
size = 36, capacity = 49
size = 37, capacity = 49
size = 38, capacity = 49
size = 39, capacity = 49
size = 40, capacity = 49
size = 41, capacity = 49
size = 42, capacity = 49
size = 43, capacity = 49
size = 44, capacity = 49
size = 45, capacity = 49
size = 46, capacity = 49
size = 47, capacity = 49
size = 48, capacity = 49
size = 49, capacity = 49
size = 50, capacity = 73
size = 51, capacity = 73
size = 52, capacity = 73
size = 53, capacity = 73
size = 54, capacity = 73
size = 55, capacity = 73
size = 56, capacity = 73
size = 57, capacity = 73
size = 58, capacity = 73
size = 59, capacity = 73
size = 60, capacity = 73
size = 61, capacity = 73
size = 62, capacity = 73
size = 63, capacity = 73
size = 64, capacity = 73
size = 65, capacity = 73
size = 66, capacity = 73
size = 67, capacity = 73
size = 68, capacity = 73
size = 69, capacity = 73
size = 70, capacity = 73
size = 71, capacity = 73
size = 72, capacity = 73
size = 73, capacity = 73
size = 74, capacity = 109
size = 75, capacity = 109
size = 76, capacity = 109
size = 77, capacity = 109
size = 78, capacity = 109
size = 79, capacity = 109
size = 80, capacity = 109
size = 81, capacity = 109
size = 82, capacity = 109
size = 83, capacity = 109
size = 84, capacity = 109
size = 85, capacity = 109
size = 86, capacity = 109
size = 87, capacity = 109
size = 88, capacity = 109
size = 89, capacity = 109
size = 90, capacity = 109
size = 91, capacity = 109
size = 92, capacity = 109
size = 93, capacity = 109
size = 94, capacity = 109
size = 95, capacity = 109
size = 96, capacity = 109
size = 97, capacity = 109
size = 98, capacity = 109
size = 99, capacity = 109
size = 100, capacity = 109

從中看出了規律:
即:ArrayList無參初始化是,容量是0,往list里面添加一個元素,容量開始擴容,擴容大小是10,當我的size到達10之后,再繼續添加時,容量是拿當前的容量乘以1.5倍,舍去小數取整,即為新容量大小。
那如果繼續無限添加元素呢,答案是:
拿最后一次擴容的容量與 整型最大值 - 8比較,如果是大於的話,取整型最大值(即:2^31 -1),如果是小於,則取整型最大值 - 8

ArrayList擴容源碼如下:

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

capacity 是list的私有屬性,也沒有提供相關的方法獲取這個值,不過我們可以通過反射來獲取這個值:

    public int getArrayListCapacity(List arrayList) {
        Class<ArrayList> arrayListClass = ArrayList.class;
        int capacity = 0;
        try {
            
            Field field = arrayListClass.getDeclaredField("elementData"); //獲取 elementData 字段
            field.setAccessible(true);// 設置為可訪問
            Object[] objects = (Object[])field.get(arrayList);
            //返回當前ArrayList實例的容量值
            capacity = objects.length;
        } catch (Exception e) {
            e.printStackTrace();
            capacity = -1;
        }
        return capacity;
    }

測試代碼:

        List<String> list = new ArrayList<>();
        System.out.println(getArrayListCapacity(list));
        for(int i=0;i<100;i++) {
            list.add(String.valueOf(i));
            System.out.println("size = " + list.size() + ", capacity = " + getArrayListCapacity(list));
        }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM