Java ArrayList源码深度解析:揭秘底层实现原理与优化技巧

一、ArrayList简介
ArrayList是Java集合框架中的一种常用数据结构,它实现了List接口,允许存储任意类型的对象。ArrayList基于动态数组实现,其底层是一个数组,通过不断扩容来满足存储需求。本文将深入解析ArrayList的源码,帮助读者了解其底层实现原理和优化技巧。
二、ArrayList源码分析
1. 类定义
```java
public class ArrayList
{
private static final long serialVersionUID = 8683452581122892189L;
private static final int DEFAULT_CAPACITY = 10;
private transient Object[] elementData;
private int size;
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ARRAY;
}
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ARRAY;
} else {
throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity);
}
}
public ArrayList(Collection extends E> c) {
elementData = c.toArray();
if ((size = elementData.length) != 0) {
// c.toArray() might (incorrectly) return "null" for an empty elementData, see 6260652
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size);
} else {
this.elementData = EMPTY_ARRAY;
}
}
}
```
2. 主要成员变量
- `elementData`:存储ArrayList元素的数组。
- `size`:ArrayList的元素数量。
3. 主要方法
(1)添加元素
```java
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!! // 确保数组有足够的空间
elementData[size++] = e;
return true;
}
```
(2)删除元素
```java
public E remove(int index) {
rangeCheck(index); // 检查索引是否有效
modCount++; // 修改次数
E oldValue = elementData(index); // 获取要删除的元素
int numMoved = size - index - 1; // 计算需要移动的元素数量
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index, numMoved); // 移动元素
elementData[--size] = null; // 设置最后一个元素为null,帮助GC
return oldValue;
}
```
(3)查找元素
```java
public E get(int index) {
rangeCheck(index); // 检查索引是否有效
return elementData(index); // 返回指定索引的元素
}
```
(4)扩容
```java
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ARRAY) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++; // 修改次数
if (minCapacity - elementData.length > 0)
grow(minCapacity); // 扩容
}
private void grow(int minCapacity) {
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1); // 扩容为原来的1.5倍
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity); // 复制数组
}
```
三、优化技巧
1. 初始化容量
在创建ArrayList时,合理设置初始容量可以减少扩容次数,提高性能。如果预估元素数量较多,可以设置较大的初始容量。
2. 使用合适的数据类型
ArrayList底层是数组,因此存储对象时,尽量使用基本数据类型包装类,如Integer、Double等,避免自动装箱和拆箱带来的性能损耗。
3. 避免频繁的删除操作
ArrayList在删除元素时,需要移动后续元素,因此频繁的删除操作会影响性能。如果需要频繁删除元素,可以考虑使用LinkedList。
4. 使用迭代器
在遍历ArrayList时,建议使用迭代器(Iterator)或for-each循环,避免使用随机访问方式(如get方法),以减少数组越界的风险。
四、总结
本文深入分析了Java ArrayList的源码,揭示了其底层实现原理和优化技巧。通过了解ArrayList的内部机制,我们可以更好地使用它,提高程序性能。在实际开发中,根据具体需求,灵活运用ArrayList,发挥其优势。






