ArrayList的扩容机制

ArrayList的扩容机制体现在当数组容量不足以容纳新元素时自动进行扩容。

当添加新元素而导致当前数组容量达到最大时,ArrayList会创建一个新的更大的数组,并将原数组中的内容复制到新创建的数组中去。先来看看ArrayList的初始化方式。

ArrayList的初始化方式

通过查看ArrayList源码的方式我们可以发现ArrayList有三种初始化方式,分别是:

1.无参初始化

2.带参初始化

可以发现,带参初始化有两种方式:

  1. 第一种就是指定数组初始化容量大小,如果指定值为负数,会抛出IllegalArgumentException异常;如果指定值为0,那么还是以ArrayList自定义的初始化大小来初始化数组容量。

  2. 第二种就是通过现在集合c来初始化,通过迭代器来构建和集合c一样的元素的ArrayList

ArrayList扩容机制

了解了ArrayList的初始化方式后,再来看看ArrayList是怎么扩容的:

使用ArrayList添加元素时,一般有以下几个方法作为备选:

一般我经常使用前两个,后两个用的很少,通过指定集合以迭代器的形式添加元素到数组。

以add(Integer e)为例,查看他的源码:

不难发现,其底层是通过调用add(e, elementDate, size)这个方法来实现添加元素到数组末尾的,再查看该方法源码:

可以看出,如果我们当前数组的容量和数组缓冲区的容量相等,那么就使用grow()方法使其扩容,elementData是什么?

回到grow()方法:

通过调用grow(int minCapacity)方法来扩容:

这里通过源码可以发现又涉及到了两个方法(不得不感叹这底层实现真是一环套一环!):copyOf()和newCapacity(int minCapacity),第一个方法很好理解,顾名思义,通过该方法的两个入参来复制数据以便创建新的数组,第二个呢?我们继续查看该方法源码:

好像快到尽头了,梳理一下newCapacity方法的逻辑:

  1. 计算当前数组容量大小

  2. 计算新数组的容量大小,通过位运算操作将oldCapacity右移一位,相当于oldCapacity/2,运算结果就是将新容量更新为就容量的1.5倍(PS:如果oldCapacity为偶数,则新增容量为1.5倍;若为奇数,新增容量是1.5倍左右。11+11/2=16会丢掉小数后数据

  3. 如果新容量小于所需最小容量,则需要进行额外的检查:

    1. 如果当前数组是默认空数组,则返回DEFAULT_CAPACITY和minCapacity中的最大值

    2. 如果所需最小容量小于0(表示溢出),则抛出OutOfMemoryError异常

    3. 否则,返回minCapacity

  4. 如果新容量未超出数组最大容量MAX_ARRAY_SIZE,返回newCapacity作为新数组的容量大小

  5. 如果新容量超出了数组最大容量,则调用hugeCapacity(int minCapacity)方法处理边界情况

查看hugeCapacity(int minCapacity)方法源码:

可以看出:

  • 入参minCapacity小于0时,和newCapacity方法一样为溢出情况,抛出OutOfMemoryError异常。

  • 若minCapacity小于MAX_ARRAY_SIZE,说明容量大小仍在合理范围,返回MAX_ARRAY_SIZE表示可容纳最大数量。

  • 若大于,说明容量过大,因此会返回Integer.MAX_VALUE,表示int类型的最大值。

举个例子:

 public class ArrayListTest {
     public static void main(String[] args) {
         ArrayList<Integer> test = new ArrayList<>(5);
         for(int i = 0; i< 5; i++){
             test.add(i);
         }
         test.add(5);
     }
 }

当执行test.add(5)时,就需要ArrayList的扩容机制给test扩容了,按照我们之前梳理的逻辑来看:

  1. 执行的方法链为:add(5) -> add(5, elementData, 5) -> grow() -> grow(5 +1) -> newCapacity(6)

  2. newCapacity(6)方法中,oldCapacity=5,newCapacity=5+5/2=7,minCapacity=6

  3. 执行判断逻辑:newCapacity - minCapacity > 0且 newCapacity - MAX_ARRAY_SIZE < 0,因此直接返回newCapacity

至此,终于看完了ArrayList扩容机制的一个完整过程,若有疑问或不当之处,欢迎指出,共同进步!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值