【Java】ArrayList底层源码分析

ArrayList底层源码分析

**先上结论:**ArrayList如果传入的参数为空,那么会在第一次添加的时候初始化容量为10,添加满后会按1.5倍扩容。如果传入的参数为8,则初始化容量大小为8,添加满后再次扩容一样会按1.5倍扩容。ArratList是线程不安全的,可以存入null,存入顺序有序,可重复,底层使用的数组实现。

1.测试代码

ArrayList list = new ArrayList();
//使用 for 给 list 集合添加 1-10 数据
for (int i = 1; i <= 10; i++) {
    list.add(i);
}
//使用 for 给 list 集合添加 11-15 数据
for (int i = 11; i <= 15; i++) {
    list.add(i);
}
list.add(100);
list.add(200);
list.add(null);

我们就以上面的代码为以进行分析debug。

打开Idea

2.设置断点

在这里插入图片描述

我们在不同的三处给list添加元素打上断点。

为什么在这三处打上断点?

原因

断点1会有第一次扩容为10

断点2会有第二次扩容为15

断点3会有第三次扩容为22

这三个断点会有三次扩容,所以会打这三个断点

3.debug分析

第一个断点分析

在这里插入图片描述

可见在第一个断点处i等于1,list还未进行扩容操作

我们强制进入add方法内部。

在这里插入图片描述

在这里插入图片描述

可以见到这里有一个ensureCapacityInternal方法,翻译过来的意思是确保内部容量传入的参数是size+1。size是内部的参数这里的参数为0,因为第一次添加,加一过后就是传入的参数为1了。

我们继续进入这个方法看

在这里插入图片描述

变量名含义
elementData是ArrayList维护的一个数组,也是最核心的数组用于帮助ArrayList存入数据。
DEFAULTCAPACITY_EMPTY_ELEMENTDATA是ArrayList维护的一个空数组
DEFAULT_CAPACITY是ArrayList维护的常量,意思是默认的容量大小

elementData数组容量为空,则在DEFAULT_CAPACITYminCapacity选出最大值并赋值给minCapacity

这里的DEFAULT_CAPACITY等于10,minCapacity等于1,所以minCapacity被赋值为10。

继续调试进入ensureExplicitCapacity方法

在这里插入图片描述

变量含义
modCount记录修改次数,集合源码中存在这个modCount变量时,基本上可以说明这个类是线程不安全的
elementData.length当前集合容量大小

当minCapacity大于当前集合容量大小则执行grow方法也就是进行扩容操作我们进入grow方法

在这里插入图片描述

变量含义
MAX_ARRAY_SIZEInteger.MAX_VALUE-8

我们将当前集合容量大小存入oldCapacity变量中,再将oldCapacity的1.5倍存入newCapacity中。当newCapacity小于minCapacity则newCapacity赋值为minCapacity也就是10。最后使用Arrays.copyOf进行扩容。

好了ensureCapacityInternal里面的方法分析完毕

进行下一步赋值

在这里插入图片描述

size++当前容量加一,elementData[0]=e。将元素e赋值给elementData下标为一。

在这里插入图片描述
在这里插入图片描述

返回add方法,此时可以看到elementData大小扩容到10,下标为0赋值为1。

我们执行完这个for循环,进入下一个断点。

在这里插入图片描述

第二个断点分析

在这里插入图片描述

这里的size为10,加1后为11传入ensureCapacityInternal方法中

在这里插入图片描述

此时elementData是不为空且有元素所以不执行if里面的语句,直接进行ensureExplicitCapacity方法

在这里插入图片描述

此时传入的参数minCapacity大于elementData.length大小进行扩容

在这里插入图片描述

将elementData容量扩容原来的1.5倍赋值给newCapacity。newCapacity大于minCapacity所以不执行if里的赋值操作,直接将elementData扩容到原来的1.5倍也就是容量为15

ensureCapacityInternal方法执行完毕回到add方法

在这里插入图片描述

elementData[10]=11

返回add方法,此时可以看到elementData大小扩容到15,下标为10赋值为11。

在这里插入图片描述

断点二分析完毕。

第三个断点和第二个断点扩容几乎一致,集合扩容到原来的1.5倍也就是22。这里不再赘述。

此文到此结束。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值