ArrayList 是基于数组实现的动态数组,它提供了一种可以动态增长和缩减的数组结构。在 ArrayList 中,当数组存储的元素个数达到上限时,会触发扩容操作,以保证其容量能够存储更多的元素。
ArrayList 扩容机制的主要过程:
- 在添加元素时,首先会判断数组是否已满。如果已满,则需要进行扩容操作;
- 扩容操作会创建一个新的大数组,并将原数组中的元素全部复制到新数组中;
- 新数组的长度通常是原数组长度的 1.5 倍(可以通过源码中的
DEFAULT_CAPACITY_INCREMENT = 12
和DEFAULT_CAPACITY = 10
来了解扩容因子)。如果指定了初始化容量,那么新数组的长度就是指定的容量大小; - 复制完元素后,会将指向原数组的引用更新为指向新数组的引用。
源码分析:
private void grow(int minCapacity) {
// 获取当前数组容量
int oldCapacity = elementData.length;
// 扩容因子,以 1.5 倍方式进行扩容
int newCapacity = oldCapacity + (oldCapacity >> 1);
// 如果新容量小于 minCapacity,则使用 minCapacity 作为新容量
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
// 如果新容量超出了最大容量,则抛出 OutOfMemoryError 异常
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// 复制旧数组中的元素到新数组中
elementData = Arrays.copyOf(elementData, newCapacity);
}
由于每次扩容都需要重新进行数据复制,所以过于频繁的扩容操作会导致性能损失。为避免频繁的扩容操作,初始化 ArrayList 对象时可以指定其容量大小,或者使用 ensureCapacity(int minCapacity)
方法预先设置其容量大小,以提高效率。同时,在添加大量元素时,也可以使用 addAll(Collection<? extends E> c)
或 addAll(int index, Collection<? extends E> c)
方法,一次性添加多个元素,以减少扩容操作的次数。