Java ArrayList 源码深度解析:揭秘背后的设计智慧

一、ArrayList简介
在Java中,ArrayList是一种非常常见的动态数组实现,用于存储一组元素。相比于其他数据结构,ArrayList具有操作灵活、性能优良等特点。本文将从源码角度,深入剖析ArrayList的设计原理和实现细节。
二、ArrayList的继承关系
ArrayList类继承自AbstractList类,并实现了List接口。以下是ArrayList的继承关系:
```
java.lang.Object
├── java.util.AbstractList
│ └── java.util.ArrayList
```
三、ArrayList的核心成员变量
1. 元素数组:elementData
elementData是ArrayList的核心成员变量,它是一个Object类型的数组,用于存储ArrayList中的元素。在ArrayList初始化时,elementData的容量默认为10。当数组容量不足时,ArrayList会自动扩容。
2. 元素数量:size
size表示ArrayList中元素的个数。每次添加或删除元素时,size都会相应地增加或减少。
四、ArrayList的构造方法
1. 无参构造方法
```java
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
```
无参构造方法初始化elementData为数组,容量为10。
2. 有参构造方法
```java
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);
}
}
```
有参构造方法根据传入的初始容量初始化elementData。如果初始容量大于0,则创建一个具有该容量的数组;如果初始容量为0,则使用EMPTY_ELEMENTDATA数组;如果初始容量小于0,则抛出IllegalArgumentException异常。
五、ArrayList的关键方法
1. 添加元素
```java
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
```
add方法用于向ArrayList中添加元素。首先,调用ensureCapacityInternal方法确保数组容量足够,然后将元素添加到数组的末尾,并更新size。
2. 扩容方法
```java
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
```
ensureCapacityInternal方法用于确保数组容量足够。如果elementData是默认空数组,则将minCapacity与默认容量进行比较,取较大值作为新的容量。然后,调用ensureExplicitCapacity方法进行扩容。
```java
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
```
ensureExplicitCapacity方法首先增加modCount,然后检查minCapacity与elementData.length的差值。如果差值大于0,说明需要扩容,此时调用grow方法进行扩容。
```java
private void grow(int minCapacity) {
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
}
```
grow方法计算新的容量为旧容量加上旧容量的一半,即扩容50%。然后,比较新容量与minCapacity,取较大值作为新的容量。如果新容量大于MAX_ARRAY_SIZE,则调用hugeCapacity方法进行扩容。最后,使用Arrays.copyOf方法将旧数组复制到新数组中。
3. 删除元素
```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; // clear to let GC do its work
return oldValue;
}
```
remove方法用于删除ArrayList中的指定元素。首先,检查索引是否有效,然后增加modCount。接着,获取要删除的元素,计算需要移动的元素数量,并使用System.arraycopy方法将后面的元素向前移动一位。最后,将删除位置的元素置为null,以便垃圾回收器回收。
六、总结
本文从源码角度深入剖析了Java ArrayList的设计原理和实现细节。通过分析ArrayList的核心成员变量、构造方法以及关键方法,我们可以更好地理解ArrayList的工作机制。在实际开发过程中,熟练掌握ArrayList的源码,有助于我们更好地优化程序性能。






