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));
            }
    
  • 相关阅读:
    微软小冰迎来了一个新姐妹:“欣小然”
    终极之战:Linux & Windows
    逆天!百度AI音箱重磅升级:最大梦想实现
    国货之光!百度飞桨与华为麒麟重磅合作
    4天如何完爆Kafka源码核心流程!
    免费P7架构师直播课!技术人员如何提升职场技能?
    ZooKeeper核心原理及应用场景
    IT自由职业者是怎么样的感受和体验
    系统梳理主流定时器算法实现的差异以及应用
    微服务架构中分布式事务实现方案怎样何取舍
  • 原文地址:https://www.cnblogs.com/qujiayuan/p/12881421.html
Copyright © 2011-2022 走看看