Java中 ArrayList的扩容机制

ArrayList的扩容机制

以下内容均基于JDK17

ArrayList的扩容会由5个方法触发

add(E e)

add(int index, E e)

addAll(Collection<? extends E> collection)

addAll(int index, Collection<? extends> collection)

ensureCapacity(int minCapacity)

与HashMap的扩容有所不同, ArrayList的扩容没有所谓的负载因子, 只是将加入元素后的实际size和当前容量比较,如果超出就会进行扩容

其主要操作是(以下size表示实际存储的数据量的数量,capacity表示内部动态数组elementData的容量):

如果采用默认的无参构造器,初始化的时候size和capacity实质都是0, 会在第一次加入元素m个后扩容至max(10, m)

否则会扩容至capacity + max(capacity >> 2 , m) (m是加入一波元素后超出原来的容量的个数),也就是扩容至1.5倍,如果不够就扩容到刚刚好够用为止

其中

add(E e)

addAll(Collection<? extends E> collection)

是在内部数组实际存储的尾部添加元素,不会有数据的位置调整

add(int index, E e)

addAll(int index, Collection<? extends> collection)

会导致原本的数据从index开始往后移动n位, 可能导致低效

ensureCapacity(int minCapacity)

这个方法的功能在于确保内部容量有minCapacity个,如果没有就触发1.5倍扩容机制,扩容到max((int)(1.5 * capacity), minCapacity)

需要注意的是,如果这个ArrayList刚刚经过无参构造初始化, 且minCapacity < 10, 不会进行扩容, 因为即使现在扩容也和加入1个元素后的扩容效果一样, 没有意义

 @Test
    public void testArrayListGrow() {
        List<Integer> list = new ArrayList<>(); // 无参构造器构造出来的, 此时内部数组elementData={}, 容量为0, size也为0
        for (int i = 1; i < 30; i++) {
            list.add(Integer.valueOf(i)); // 断点Condition: i == 1 || i == 11 || i == 16 || i == 23
            // i = 1 容量从0 -> 10
            // i = 11 容量从10 -> 15
            // i = 16 容量从 15 -> 22
            // i = 23 容量从 22 -> 33 ...
        }

        list = new ArrayList<>(1);
        for (int i = 1; i < 30; i++) {
            list.add(Integer.valueOf(i)); // 断点Condition: i == 2 || i == 3 || i == 4 || i == 5 || i == 7 || i == 10 || i == 14 || i == 20 || i == 29
            // i = 2 容量 1 -> 2
            // i = 3 容量 2 -> 3
            // i = 4 容量从3 -> 4
            // i = 5 容量从4 -> 6
            // i = 7 容量从6 -> 9
            // i = 10 容量从9 -> 13
            // i = 14 容量从13 -> 19
            // i = 20 容量从19 -> 28
            // i = 29 容量从28 -> 42
        }

用上面的代码进行调试单步进入底层add可以看到扩容操作

  • 9
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值