关于 ArrayList 初始容量和扩容源码解读

众所周知,ArrayList的底层是数组,那么ArrayList的数组容量到底是多少呢?

首先,先new一个ArrayList,然后向集合中添加11个元素,至于为什么是11个,下面再说。

然后我们debug一点一点来看:

我们看到,在执行ArrayList的空参构造的时候,执行了一段代码,那么这段代码表示什么什么含义呢?

可以看到在ArrayList类中定义了两个成员变量,通过注释我们可以知道elementData表示数组缓冲区,而DEFAULTCAPACITY_EMPTY_ELEMENTDATA 是当ArrayList类加载的时候创建的一个空数组,此时把该空数组赋值给数组缓冲区。所以我们可以知道初始化一个ArrayList集合,如果没有指定容量的时候,默认初始容量为0。

接着,我们向集合中添加第一个元素。

进入到add()方法,看到会首先执行ensureCapacityInternal(size + 1),size是ArrayList的成员变量,表示集合的大小,继续跟进ensureCapacityInternal方法,

因为此时数组缓冲区为空,所以会为minCapacity进行赋值,可以看到默认容量为10,继续跟进ensureExplicitCapacity()方法,

这里首先对当前集合的修改次数进行累加,上一步对minCapacity进行了赋值,可以看到当最小容量大于数组缓冲区的大小时,就会去执行grow()方法,继续跟进,

到了这里我们终于找到了对集合进行扩容的地方,可以看出,先是获取了数组缓冲区的长度赋给了oldCapacity,然后进行了对oldCapacity进行位移运算(右移一位,也就是变为原来的1/2),并把结果赋给newCapacity,然后判断newCapacity和minCapcity的大小,而此时newCapacity的值为0,然后对newCapacity重新赋值,到最后重新对数组缓冲区赋值,到这里,数组缓冲区的大小为10,也就是完成了第一次扩容。

从上一步可以看出,当集合中的元素达到第一次扩容后的上限(也即是10)后,会继续对集合进行扩容,那么再次扩容多少呢?

当我们向集合中添加到11个元素时(这里就是为什么要向集合中添加11个元素的原因),会再次对进行再次扩容,根据刚才分析的,可以算出此时的集合被扩容到15,也就是原来的3/2(这里的3/2是代码中根据位移运算计算出来的)。

至此我们可以得到结论,创建一个集合时,集合的初始容量为0,在第一次添加元素的时候,会对集合进行扩容,扩容之后,集合容量为10;之后,当向集合中添加元素达到集合的上限(也就是minCapacity大于elementData.length)时,会对集合再次扩容,扩容为原来的3/2。

猜你喜欢

转载自blog.csdn.net/weixin_38814131/article/details/82187020