ArrayList 源码解析
1 初始化
ArrayList类定义,通过类定义可以分析出ArrayList具备了RandomAccess(支持随机访问)、Cloneable(可以被复制)、Serializable(序列化)
1 | public class ArrayList<E> extends AbstractList<E> |
初始化类属性,DEFAULT_CAPACITY(默认容量大小)、EMPTY_ELEMENTDATA(用来置空数组的)、DEFAULTCAPACITY_EMPTY_ELEMENTDATA(初始化时候的数组,根据下面代码看来,初始化的时候elementData默认指向DEFAULTCAPACITY_EMPTY_ELEMENTDATA)、elementData(存放元素)、size(当前数组大小)
1 | /** |
添加元素
ArrayList通过add方法来进行添加元素,ensureCapacityInternal
这个方法比较复杂,稍后进行讲解,其实ArrayList底部还是数组,添加元素无非是给指定下标指向e到对象而已,然后size++。从这里看来ArrayList是非线程安全的。
1 | public boolean add(E e) { |
接下来看看ensureCapacityInternal
这个方法
1 | private void ensureCapacityInternal(int minCapacity) { |
接下来看看关键性的grow方法
1 | private void grow(int minCapacity) { |
上述方法主要是当数组长度不够时,自动增长数组的长度,增长因子是当前长度的二分之一。也就是说增长后=oldLength+oldLength>>1
添加元素到指定位置
添加元素到指定位置,这个方法效率比较低,需要进行对元素的大量移动操作1
2
3
4
5
6
7
8
9
10
11public void add(int index, E element) {
//判断是否超过当前数组大小
rangeCheckForAdd(index);
ensureCapacityInternal(size + 1); // Increments modCount!!
//index开始的元素后移一位
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}
删除某个位置的元素
基本跟add(int index, E element)这个方法没有太大区别,一个是数组向后移动,一个是向前移动1
2
3
4
5
6
7
8
9
10
11
12
13
14public 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;
}
删除某个元素
删除某个元素的时候,主要是根据equals方法去判断是否是同一个对象的。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32public boolean remove(Object o) {
if (o == null) {
//移除null对象
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {
//主要是调用equals方法判断是否是同一个对象
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}
/*
* Private remove method that skips bounds checking and does not
* return the value removed.
*/
private void fastRemove(int index) {
modCount++;
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
}
可以看到 ArrayList 中删除和添加都使用到了 System.arraycopy 这个方法。这个方法是一
个 native 的方法。如下1
2
3public static native void arraycopy(Object src, int srcPos,
Object dest, int destPos,
int length);
@src — 这是源数组 @srcPos — 这是源数组中的起始位置 @dest — 这是目标数组 @destPos — 这是目标数据中的起始位置 @length — 这是一个要复制的数组元素的数目
比如:1
2
3
4
5int arr1[] = {0,1,2,3,4,5};
int arr2[] = {0,10,20,30,40,50};
System.arraycopy(arr1,0,arr2,1,2);
arr2 = [0,0,1,30,40,50];
System.arraycopy 方法的实现使用C++实现的,实现原理就是直接操作内存地址操作。因为数组是一段连续的内存地址。