1. ArrayList基础与构造函数解析
ArrayList作为Java集合框架中最常用的动态数组实现,其内部通过数组来存储元素。与普通数组不同,ArrayList能够自动扩容以适应元素的动态增减。理解其底层实现机制,对于编写高性能Java代码至关重要。
1.1 三种构造函数的差异与选择
ArrayList提供了三种构造函数,每种都有其特定的使用场景:
java复制// 无参构造 - 懒初始化策略
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
// 指定初始容量
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity);
}
}
// 通过集合初始化
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
if ((size = elementData.length) != 0) {
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
this.elementData = EMPTY_ELEMENTDATA;
}
}
无参构造的懒加载设计:这是最容易被误解的一点。无参构造并不会立即分配10个元素的空间,而是使用一个空数组标记DEFAULTCAPACITY_EMPTY_ELEMENTDATA。只有在首次添加元素时,才会真正分配默认容量(10)。这种设计避免了创建未使用ArrayList时的内存浪费。
实际开发中,如果能预估元素数量,使用指定容量的构造函数可以避免多次扩容带来的性能损耗。例如,已知要存储约1000个元素,直接
new ArrayList(1000)比默认构造后自动扩容要高效得多。
1.2 内部数组与容量管理
ArrayList内部维护的核心字段包括:
transient Object[] elementData:实际存储元素的数组private int size:当前元素数量(非数组长度)private static final int DEFAULT_CAPACITY = 10:默认初始容量private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8:最大数组限制
**容量(capacity)与
