ArrayList的扩容原理
摘要:本文旨在透彻解析 Java 中ArrayList的动态扩容机制。 从原理到实践,我们将揭示这一流行数据结构背后的调整策略,为开发者提供优化代码和提升性能的见解。
引言
在数据集合持续增长的现代编程中,如何优雅地管理内存是衡量一个优秀程序的关键。ArrayList,作为Java集合框架的一员,优秀地解决了数组静态大小的限制。本文将详解ArrayList动态扩容的内部工作机制。
1. 底层代码
private void ensureCapacityInternal(int minCapacity) {
// 如果ArrayList为空,则选择默认容量和传入容量的较大值作为新容量
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
// 确保ArrayList的容量足够存储minCapacity个元素
ensureExplicitCapacity(minCapacity);
}
private void ensureExplicitCapacity(int minCapacity) {
// 修改操作次数加1
modCount++;
// 如果minCapacity大于当前容量,则进行扩容操作
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
private void grow(int minCapacity) {
// 原容量
int oldCapacity = elementData.length;
// 新容量是原容量的1.5倍,并向上取整
int newCapacity = oldCapacity + (oldCapacity >> 1);
// 如果新容量小于minCapacity,则直接使用minCapacity作为新容量
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
// 如果新容量大于最大容量,则使用最大容量作为新容量
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// 将原始数组拷贝到新数组中,实现扩容
elementData = Arrays.copyOf(elementData, newCapacity);
}
private static int hugeCapacity(int minCapacity) {
// 如果minCapacity大于最大容量,则抛出OutOfMemoryError异常
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
2. ArrayList扩容方式原理
- 当需要添加元素时,ArrayList会先判断当前容量是否足够,如果不足够,则需要进行扩容操作。
- 扩容操作的第一步是调用
ensureCapacityInternal
方法,该方法用于确定扩容后的最小容量。 - 如果ArrayList为空,则选择默认容量和传入容量的较大值作为新容量。
- 然后调用
ensureExplicitCapacity
方法,该方法用于判断是否需要进行扩容操作。 - 在
ensureExplicitCapacity
方法中,修改操作次数加1,然后判断如果需要的最小容量大于当前容量,则进行扩容操作。 - 扩容操作的第二步是调用
grow
方法,该方法用于计算新的容量并进行扩容。 - 首先获取当前的容量,然后计算新的容量,一般是原容量的1.5倍,并向上取整。
- 如果新容量小于所需的最小容量,则直接使用最小容量作为新容量。
- 如果新容量超过了最大容量限制,则使用最大容量作为新容量。
- 最后,通过调用
Arrays.copyOf
方法,将原始数组拷贝到新数组中,实现扩容。
3. 结论
总的来说,ArrayList的扩容方式是通过动态调整容量大小的方式来实现的。当需要添加元素时,如果当前容量不足够,就会进行扩容操作。扩容操作会计算新的容量大小,并将原始数组拷贝到新的数组中,从而实现容量的增加。扩容操作可以提高ArrayList的添加元素的效率,但是在进行扩容时会带来一定的性能开销。因此,在使用ArrayList时,如果事先能够估计到元素的数量,可以通过调用
ensureCapacity
方法来指定初始容量,从而减少扩容次数,提高效率。
4. 参考文献
- Effective Java, Joshua Bloch
- Java Collection Framework documentation
- ArrayList source code analysis
关于作者:猿究院——屠龙少年SlayMaster
版权声明:创作不易,版权需敬, 笑一笑,传播正能量!
评论区:灵感闪现,友谊加码, 一句顶俏,乐开花!