【揭秘】初探ArrayList的1.5倍扩容,初探arraylist1.5
【揭秘】初探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都可以从中学会一点东西,我会继续努力!
相关文章
- 暂无相关文章
用户点评