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

一、ArrayList简介
ArrayList是Java集合框架中的一个常用类,它实现了List接口,提供了动态数组的功能。在Java开发中,ArrayList因其高效的数据操作能力和灵活的扩容机制而被广泛应用。本文将深入解析ArrayList的源码,帮助读者更好地理解其底层原理和优化技巧。
二、ArrayList的继承关系与构造方法
ArrayList类继承自AbstractList类,并实现了List接口。其构造方法如下:
```java
public ArrayList(int initialCapacity) {
super();
if (initialCapacity <= 0)
throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity);
this.elementData = new Object[initialCapacity];
}
public ArrayList() {
this(10);
}
public ArrayList(Collection extends E> c) {
elementData = c.toArray();
if ((size = elementData.length) != 0) {
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size);
} else {
this.elementData = EMPTY_ELEMENTDATA;
}
}
```
1. `ArrayList(int initialCapacity)`:创建一个具有指定初始容量的ArrayList实例。如果初始容量小于等于0,则抛出IllegalArgumentException异常。
2. `ArrayList()`:创建一个默认初始容量为10的ArrayList实例。
3. `ArrayList(Collection extends E> c)`:创建一个包含指定集合c元素的ArrayList实例。如果c为null,则抛出NullPointerException异常。
三、ArrayList的核心方法
1. `add(E e)`:在列表的末尾添加元素。首先检查容量是否足够,如果不足,则进行扩容。扩容操作是将现有数组复制到一个更大的数组中。
```java
public boolean add(E e) {
modCount++;
ensureCapacityInternal(size + 1);
elementData[size++] = e;
return true;
}
```
2. `remove(int index)`:移除指定索引处的元素。首先检查索引是否有效,然后通过数组元素后移的方式实现移除操作。
```java
public E remove(int index) {
modCount++;
if (index >= size || index < 0)
throw new IndexOutOfBoundsException();
E oldValue = elementData(index);
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index + 1, elementData, index, numMoved);
elementData[--size] = null;
return oldValue;
}
```
3. `get(int index)`:返回指定索引处的元素。首先检查索引是否有效,然后直接返回数组中对应索引的元素。
```java
public E get(int index) {
if (index >= size || index < 0)
throw new IndexOutOfBoundsException();
return elementData(index);
}
```
4. `set(int index, E element)`:将指定索引处的元素替换为指定的元素。首先检查索引是否有效,然后通过数组元素后移的方式实现替换操作。
```java
public E set(int index, E element) {
if (index >= size || index < 0)
throw new IndexOutOfBoundsException();
E oldValue = elementData(index);
elementData[index] = element;
return oldValue;
}
```
四、ArrayList的扩容机制
当ArrayList的元素个数超过数组的容量时,需要进行扩容操作。ArrayList的扩容机制如下:
1. 新容量是旧容量的1.5倍加上1。
```java
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
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;
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
}
```
2. 如果旧容量小于默认容量(10),则将默认容量作为最小容量。
3. 如果新容量小于最小容量,则将最小容量作为新容量。
4. 如果新容量大于最大数组容量(Integer.MAX_VALUE - 8),则使用`hugeCapacity`方法计算新容量。
5. 使用`Arrays.copyOf`方法将旧数组复制到新数组中,完成扩容操作。
五、总结
本文深入解析了Java ArrayList的源码,包括其继承关系、构造方法、核心方法以及扩容机制。通过阅读本文,读者可以更好地理解ArrayList的底层原理和优化技巧,为实际开发提供参考。






