说一下ArrayList的默认大小?它是如何进行扩容的?
参考回答**
1. ArrayList 的默认大小
在 Java 中,ArrayList 的初始默认容量为 10。
当通过无参构造函数创建一个 ArrayList 时:
ArrayList
此时 ArrayList 的容量并未真正分配。
当第一次向 ArrayList 添加元素时(如 list.add(1)),它会分配默认大小为 10 的数组。
- ArrayList 的扩容机制
当 ArrayList 中的元素数量超过当前容量时,ArrayList 会自动扩容。具体机制如下:
扩容倍数:
当数组容量不足时,ArrayList 会将容量扩展为 原容量的 1.5 倍。
新容量计算公式:
newCapacity = oldCapacity + (oldCapacity >> 1);
其中,
1
表示右移 1 位,相当于除以 2。
扩容操作:
创建一个新的更大的数组。
将原数组中的元素拷贝到新数组中。
示例:
初始容量为 10,当元素数量超过 10 时:
第一次扩容:容量从 10 扩展为 15。
第二次扩容:容量从 15 扩展为 22。
依此类推。
详细讲解与扩展
1. ArrayList 的容量与大小
大小(size):指当前 ArrayList 中实际存储的元素数量。
容量(capacity):指内部数组的长度,即 ArrayList 可存储的最大元素数。
默认情况下,ArrayList 的初始容量为 10,但可以通过构造函数指定初始容量:
ArrayList
2. ArrayList 的扩容源码分析
在 JDK 的 ArrayList 实现中,扩容逻辑在 ensureCapacityInternal() 方法中定义:
private void ensureCapacityInternal(int 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 为准
if (newCapacity – minCapacity < 0)
newCapacity = minCapacity;
// 如果扩容后超过 Integer.MAX_VALUE,则抛出异常
if (newCapacity – MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// 复制到新数组
elementData = Arrays.copyOf(elementData, newCapacity);
}
扩容说明:
每次扩容为原容量的 1.5 倍,但不会小于所需的最小容量(minCapacity)。
如果新容量超过 Integer.MAX_VALUE,则使用 hugeCapacity() 处理。
- 扩容的性能开销
扩容涉及到 创建新数组 和 复制数据,因此扩容操作是一个相对昂贵的操作,特别是当数据量较大时,复制开销较高。
减少扩容开销的建议:
指定初始容量:
如果可以预估列表的元素数量,建议在创建 ArrayList 时指定初始容量。
ArrayList
批量添加元素:
如果需要批量插入大量数据,可以使用 ensureCapacity() 方法预先扩容。
list.ensureCapacity(1000); // 提前扩容,减少后续扩容次数
4. ArrayList 的扩容规则总结
阶段 容量变化(默认)
初始容量 10
第一次扩容 15
第二次扩容 22
第三次扩容 33
第四次扩容 49
5. 与其他集合类的比较
集合类型 容量特性 扩容方式
ArrayList 动态数组,无初始容量则默认 10 扩容为原容量的 1.5 倍
LinkedList 基于链表,无需扩容 动态增加节点,无容量限制
HashMap 默认容量为 16 容量翻倍
Vector 动态数组,默认容量为 10,可配置扩容增长倍数 扩容为原容量的 2 倍
示例代码
以下代码展示了 ArrayList 扩容的原理:
import java.util.ArrayList;
public class ArrayListExpansion {
public static void main(String[] args) {
ArrayList
// 添加 15 个元素,触发扩容
for (int i = 0; i < 15; i++) {
list.add(i);
System.out.println(“Size: ” + list.size() + “, Capacity: ” + getCapacity(list));
}
}
// 获取 ArrayList 的容量(通过反射)
private static int getCapacity(ArrayList<?> list) {
try {
java.lang.reflect.Field field = ArrayList.class.getDeclaredField(“elementData”);
field.setAccessible(true);
Object[] elementData = (Object[]) field.get(list);
return elementData.length;
} catch (Exception e) {
e.printStackTrace();
}
return -1;
}
}
输出示例:
Size: 1, Capacity: 10
Size: 10, Capacity: 10
Size: 11, Capacity: 15
Size: 15, Capacity: 15
总结
默认大小:ArrayList 默认初始容量为 10。
扩容机制:当容量不足时,扩容为原容量的 1.5 倍。
性能优化:通过预设初始容量或调用 ensureCapacity() 方法,减少扩容次数。
注意事项:扩容涉及数组复制,性能开销较大,需根据实际场景合理设计容量。