ArrayList 是一种常用的动态数组数据结构,底层依托于一个 Object[] 数组,当数组已满或者添加元素个数达到预分配的容量时,需要对数组进行扩容以继续添加元素。在 JDK1.8 中,时常听到关于 ArrayList 扩容的问题,接下来我将详细介绍 ArrayList 的底层数组如何扩容。
ArrayList 底层数组的定义
在 JDK1.8 的 ArrayList 中,底层数组的定义如下:
transient Object[] elementData; // 非私有的、仅在类 ArrayList 内部使用的数组,用于存储添加的元素。
其中,transient
关键字表示该字段不会被序列化。
ArrayList 底层数组扩容机制
ArrayList 中通过 ensureCapacityInternal
方法来判断是否需要对底层数组进行扩容,具体流程如下:
- 首先判断是否需要扩容。
private void ensureCapacityInternal(int minCapacity) {
// 如果底层数组为空,则分配一个默认容量的数组
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
// 如果需要的最小容量大于现有数组容量,则需要扩容
ensureExplicitCapacity(minCapacity);
}
- 调用
ensureExplicitCapacity
方法扩容。
private void ensureExplicitCapacity(int minCapacity) {
// 修改扩容标志位
modCount++;
// 扩容时实际需要的最小容量为目前容量和需要的最小容量中的较大者
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
- 在
grow
方法中,根据不同的情况进行扩容。
private void grow(int minCapacity) {
// 获取此时底层数组的长度
int oldCapacity = elementData.length;
// 新容量为原来的1.5倍,向上取整
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
// 将底层数组复制到新的扩容底层数组中
elementData = Arrays.copyOf(elementData, newCapacity);
}
扩容时,ArrayList 将底层数组的新容量计算为原来容量的1.5倍。同时,若所需的最小容量大于计算出的容量,则以所需容量为准。最后,通过调用 Arrays.copyOf
方法将原来的数组元素全部复制到新数组中去。
示例说明
示例一
下面是一段示例代码,演示 ArrayList 的扩容机制。
ArrayList<Integer> list = new ArrayList<>();
// 添加21个元素
for (int i = 1; i < 22; i++) {
list.add(i);
}
System.out.println("当前数组容量:" + list.size());
输出结果如下:
当前数组容量:21
从结果可以看出,当添加元素个数达到数组容量的上限时,ArrayList 自动对底层数组进行扩容。
示例二
在一些场景下,我们需要对 ArrayList 进行优化,比如初始化时指定 ArrayList 的容量大小。下面是一段这样的示例代码:
ArrayList<Integer> list = new ArrayList<>(100);
// 添加100个元素
for (int i = 1; i < 101; i++) {
list.add(i);
}
System.out.println("当前数组容量:" + list.size());
输出结果如下:
当前数组容量:100
从结果可以看出,当初始化时指定 ArrayList 的容量大小时,不需要进行数组扩容,大大提高了 ArrayList 的效率。
总结
ArrayList 底层数组的扩容机制是 ArrayList 实现动态数组的关键。扩容时,通过一定规则计算新的容量大小,并将原始数组复制到新的底层数组中,以完成实现动态数组的功能。在实际应用中,如有需要,可以根据不同情况对 ArrayList 进行一定程度的优化,以提高应用效率。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:聊一聊jdk1.8中的ArrayList 底层数组是如何扩容的 - Python技术站