ArrayList扩容机制(源码级)直接Debug模式带你手撕源码

本文深入解析ArrayList的扩容机制,从构造方法开始,探讨初始容量、空实例共享数组,到添加元素时如何触发扩容。通过Debug模式跟踪源码,详细解释ensureCapacityInternal、ensureExplicityCapacity及grow方法的工作流程,展示ArrayList如何动态调整容量以适应元素增长,最终实现扩容操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

     ArrayList<String> list = new ArrayList<>();
    

首先我们先创建初始化一个ArrayList,在初始化时,会调用ArrayList的构造方法,有几个要记住的点,如下:

请区别开size和CAPACITY(容量),容量相当于一个杯子容量为500ml,size相当于你实际装进去的水。

 

默认初始容量:

private static final int DEFAULT_CAPACITY = 10;

 

用于空实例的共享空数组实例:

private static final Object[] EMPTY_ELEMENTDATA = {};

 

用于默认大小的空实例的共享空数组实例:

private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

存储 ArrayList 元素的数组缓冲区:

transient Object[] elementData;

注意: ArrayList 的容量就是这个数组缓冲区的长度。当添加第一个元素时,任何具有 elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA 的空 ArrayList 都将扩展为 DEFAULT_CAPACITY

 

ArrayList 的大小(它包含的元素数量):

private int size;

好了,了解了以上之后,我们调用构造方法:

    

    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

请注意,elementData是个Object的数组,只被声明,没有被初始化,该构造方法相当于把一个空的Object数组赋给elementData,size为0。所以该ArrayList的容量为默认初始容量DEFAULT_CAPACITY = 10

 

这样,一个ArrayList就被初始化好了,现在我们调用它的add方法。

list.add("1");

通过Debug模式,我们会追溯其源码。

 

90326fe303d74ae0b7a6f497ed9c86a8.png

然后进入到ArrayList的add方法中。

f29e2884be264b349678e3f0fc780918.png

 

这里面又调用了ensureCapacityInternal方法,把size+1传进去,相当于把原来的size(此时为0)+1传进去。

我们进去再看看ensureCapacityInternal方法

 

2f2028d35a724f8dbd70ed23d582bab9.png

此时,最小容量为1,然后进入if语句中。还记得吗,elementData在我们初始化ArrayList的时候,构造方法把等号右边这个数组赋给了它,所以判断为true

 

c884ac8846704111b2bedeae21feb7e1.png

现在,取DEFAULT_CAPACITY与最小容量的最大值,并且再赋给minCapacity,此时DEFAULT_CAPACITY==10,所以minCapacity==10

 

dde40d6f6ec84d2b96a111f5cf35add5.png

然后进入ensureExplicityCapacity方法中,把minCapacity传进去。

modCount++这行代码暂且可以不管,与本次扩容无关,我们直接看下面的代码

 

993d9351cacd4c98b72bdce3da0b5738.png

进行一次比较,minCapacity此时为10,elementData这个数组的长度,因为现在为空,所以elementData.length ==0,判断为true,运行下面的grow方法,并且把minCapacity传进去

 

a497d0fa271d4b038d7612e669c68b78.png

oldCapacity是原来的容量 = elementData.length = 0,

newCapacity是新容量 = oldCapacity + (oldCapacity >> 1)  (位运算符,向右移1位可以理解为除以2) 

所以newCapacity = 0

e32855bd7313401ba656b8af6af272d5.png

 进行比较,newCapacity显然小于minCapacity(10)

 

所以把最小容量赋值给新容量,newCapacity =10;

f7da90279c124fe6b3db147f601c01e7.png

再进行一次比较,新容量是否大于ArrayList所定义的最大限量的容量,具体值为图所示,显然为false,所以newCapacity = hugeCapacity(minCapacity)不用执行。

0fba0cf3d4974888a471053ae44f08e3.png

 然后,执行Arrays.copyOf()方法,该方法会复制指定的数组,截断或填充空值(如有必要),使副本具有指定的长度,相当于把elementData的length扩充为10,并且填充默认值。

 

至此,扩容完成。

2907d32b22a54acb9701d133c6ba81c7.png

最后返回到add方法中,将elementData的size(请区别现在的size变量和上述的length),当前size为0,所以把e(是我们传进来的String "1") 赋给 坐标为elementData[0] 的元素,然后ArrayList的size++。

 

还有一些未补充和没说完整的,以后再补充。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值