zoukankan      html  css  js  c++  java
  • 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));
            }
    
  • 相关阅读:
    627. Swap Salary
    176. Second Highest Salary
    596. Classes More Than 5 Students
    183. Customers Who Never Order
    181. Employees Earning More Than Their Managers
    182. Duplicate Emails
    175. Combine Two Tables
    620. Not Boring Movies
    595. Big Countries
    HDU 6034 Balala Power! (贪心+坑题)
  • 原文地址:https://www.cnblogs.com/qujiayuan/p/12881421.html
Copyright © 2011-2022 走看看