欢迎访问悦橙教程(wld5.com),关注java教程。悦橙教程  java问答|  每日更新
页面导航 : > > > 文章正文

【揭秘】初探ArrayList的1.5倍扩容,初探arraylist1.5

来源: javaer 分享于  点击 41483 次 点评:172

【揭秘】初探ArrayList的1.5倍扩容,初探arraylist1.5


关于ArrayList自动扩容的一点探索:

前天,群里有人向我提出了一个问题:为什么ArrayList扩容机制是原来容量的1.5倍方式扩容?说实话,这个问题一开始把我问蒙了。后来,仔细一想。这个1.5倍扩容是基于jdk7以及以上版本而言的,我当初只是大概看了一眼,实在是给不出一个准确详尽的解释。于此,如梗在喉,觉得有必要抽出时间一探究竟,让我们把这纷扰看得清清楚楚明明白白真真切切!

获取ArrayList实例的容量的方法

通过查看ArrayList源码可知 ,elementData 是一个对象数组,用于存储ArrayList的元素,ArrayList的容量就是该数组的长度。所以,只要得到elementData,就可以知道ArrayList实例的容量。由于elementData是私有的,可以通过反射的方式获取,代码如下:


ArrayList实例初始化

先来看一个小例子


运行结果:


容量大小:0

元素个数:0


当然,ArrayList初始化方式有几种。我选择一个常用的作为实例。下面是ArrayList源码:

由上可知:初始化比较简单,elementData赋值一个空的数组。

1.5倍的扩容

向ArrayList实例中添加1个元素


运行结果:

容量:10

大小:1


向ArrayList实例中添加11个元素



运行结果:

容量:15

大小:11


我们发现,当向hi中添加第11个元素时,hi的容量扩容到原来的1.5倍。

为什么扩容了1.5倍?

查看ArrayList的add源码:

add方法是通过在list的尾部追加元素的方法,添加数据的。

其中,调用了一个叫ensureCapacityInternal方法,实现list的容量换算等:



注意:参数传的是当前需要的最小的容量,方法首先确认当前ArrayList实例是否为空,如果为空则比较所需容量和默认容量,取其大者作为所需最小容量值。然后执行ensureExplicitCapacity进一步确定容量,以及是否需要扩容。当所需最小容量大于当前elementData数组长度时,要进行扩容操作。


以上只是真实容量和所需容量的比较,其目的是计算出list的最终容量。真正实现扩容的方法是grow方法:


通过上述:我们大概可知当add一个元素时候的扩容流程。

添加一个元素,首先计算当前的list所需最小的容量大小,是否需要扩容等。当需要扩容时:

1.得到当前的ArrayList的容量(oldCapacity)

2.计算除扩容后的新容量(newCapacity),其值(oldCapacity + (oldCapacity >> 1))约是oldCapacity 的1.5倍

这里采用的是移位运算(关于移位运算,后续会讲到)。为什么采用这种方法呢?应该是出于效率的考虑。

3.当newCapacity小于所需最小容量,那么将所需最小容量赋值给newCapacity。

4.newCapacity大于ArrayList的所允许的最大容量,处理。

5.进行数据的复制,完成向ArrayList实例添加元素操作。


由上述可知,所说的1.5倍扩容,并不确切。最后真正的容量,可能不止1.5倍,也许还要大。


写在后面的话:

作为coder,就是需要不断在问题中积累的,不断丰富自己的知识结构和所从事技术的认知。上述写的可能不够生动,只是希望尽力让每一个看到的coder都可以从中学会一点东西,我会继续努力!

相关文章

    暂无相关文章

用户点评