ArrayList 是 Java 中常用的一种 List 容器,其内部使用数组实现。该容器的主要功能就是用于存储和操作各种数据类型的元素。在本文中,我们将对 ArrayList 的源码进行详细分析,以帮助读者更好地了解其内部实现机制。
常用方法
在开始分析 ArrayList 的源码之前,我们先来简要介绍一下该容器的常用方法。
add 方法
该方法用于向 ArrayList 尾部添加元素,其函数签名如下:
public boolean add(E e)
其中,E 表示该容器中存放的元素类型。该方法会返回一个布尔值,表示元素是否添加成功。
get 方法
该方法用于获取指定位置处的元素,其函数签名如下:
public E get(int index)
其中,index 表示要获取的元素在 ArrayList 中的下标,E 表示元素的类型。该方法会返回获取到的元素。
remove 方法
该方法用于移除指定位置处的元素,其函数签名如下:
public E remove(int index)
其中,index 表示要移除的元素在 ArrayList 中的下标,E 表示元素的类型。该方法会返回被移除的元素。
size 方法
该方法用于获取 ArrayList 中的元素数量,其函数签名如下:
public int size()
该方法会返回 ArrayList 中元素的个数,即数组的长度。
构造函数
在分析源码之前,我们先来看一下 ArrayList 的构造函数。ArrayList 有 3 种不同的构造函数,分别如下:
public ArrayList()
public ArrayList(Collection<? extends E> c)
public ArrayList(int initialCapacity)
第一种构造函数用于创建一个空的 ArrayList,第二种构造函数用于创建一个包含指定 Collection 中所有元素的 ArrayList,第三种构造函数用于创建一个指定初始容量的 ArrayList。
源码分析
接下来,我们将依次分析 ArrayList 中的各个方法及其实现机制。
成员变量
ArrayList 中包含了如下成员变量:
transient Object[] elementData;
private int size;
private static final int DEFAULT_CAPACITY = 10;
其中,elementData 表示存储元素的数组,size 表示 ArrayList 中元素的数量,DEFAULT_CAPACITY 表示该容器默认的初始容量。
add 方法实现
ArrayList 的 add 方法的实现如下:
public boolean add(E e) {
modCount++;
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
add 方法首先会将 modCount(修改计数器)加 1,然后会调用 ensureCapacityInternal 方法保证 ArrayList 中的数组可以容纳新的元素。然后将新的元素添加到数组的末尾,并将 size (元素数量)加 1。最后,将 true 返回表示元素添加成功。
get 方法实现
ArrayList 的 get 方法的实现如下:
public E get(int index) {
rangeCheck(index);
return elementData(index);
}
get 方法首先会调用 rangeCheck 方法,确保传入的下标是合法的。如果下标不合法,rangeCheck 方法会抛出一个 IndexOutOfBoundsException 异常。如果下标合法,get 方法则会调用 elementData(index) 方法获取对应下标位置的元素。
elementData(index) 方法的实现如下:
E elementData(int index) {
return (E) elementData[index];
}
该方法直接返回数组中对应下标的元素。
remove 方法实现
ArrayList 的 remove 方法的实现如下:
public E remove(int index) {
modCount++;
rangeCheck(index);
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 方法首先会将 modCount(修改计数器)加 1,并调用 rangeCheck 方法,确保传入的下标是合法的。如果下标不合法,rangeCheck 方法会抛出一个 IndexOutOfBoundsException 异常。
如果下标合法,则会获取对应下标位置的元素,并将 size 减 1。然后,使用 System.arraycopy 方法将下标为 index+1 开始的元素向前移动一个位置(相当于删除了下标为 index 的元素)。清空原数组的最后一个元素,并将被删除的元素返回。
private 方法
除了上述三个常用方法外,ArrayList 中还包含了很多 private 方法,这些方法主要用于实现 ArrayList 内部使用的各种机制。其中比较重要的方法如下:
- ensureCapacityInternal 方法:该方法用于确保 ArrayList 中的数组可以容纳新的元素。在需要添加新元素时,先调用该方法,如果当前数组容量不足,就会扩容。
- grow 方法:该方法用于对 ArrayList 进行扩容。当 elementData 数组已满时,就会调用该方法进行扩容操作。
- rangeCheck 方法:该方法用于判断传入的下标是否合法。如果下标不合法,该方法会抛出一个 IndexOutOfBoundsException 异常。
- trimToSize 方法:该方法用于缩小 elementData 数组的容量。调用该方法后,elementData 数组的长度会被设置为当前 elementData 中包含的元素数量。
- toArray 方法:该方法用于将包含在 ArrayList 中的元素存储到一个数组中。
- clone 方法:该方法用于创建并返回 ArrayList 的副本。
总结
通过以上分析,我们可以看出,ArrayList 是一种使用数组实现的 List 容器。它提供了丰富的方法,使得用户能够方便地对其中的元素进行增、删、查等操作。ArrayList 内部使用了很多机制来优化其性能,如扩容、压缩等。如果您对 ArrayList 的实现机制感兴趣,建议花更多时间深入研究其源代码。