ArrayList 源码分析
ArrayList 是平时常用的数据存储结构,它基于动态数组,支持随机访问,值得一提的是:它是不安全的。造成这种不安全的原因主要是:在在多线程环境下,向 ArrayList 添加或移除时,会产生数组越界等问题。推荐使用 Vector、CopyOnWriteArrayList 代替。
ArrayList 与 Array 区别:
- Array 包含的是基本类型和对象类型,而ArrayList 只能包含对象类型
 - Array 的大小的是固定的,所以在定义数组的时候尽量确定需要的数组大小,而ArrayList 的大小是动态变化的,当容量不足时能自动扩容
 - ArrayList 可以看作Array的增强版,提供了更多的方法和特性,在查找等操作上更方便
 
定义
1  | public class ArrayList<E> extends AbstractList<E>  | 
ArrayList 支持泛型,继承了 AbstractList,在实现了List接口的同时,实现了一下三个接口:
- RandomAccess — 随机访问,即通过元素的序号快速获取对象
 - Cloneable — 覆盖了 clone(),能被克隆
 - Serializable — 支持序列化
 
属性
1  | private static final long serialVersionUID = 8683452581122892189L;  | 
其中,size 指 ArrayList 的大小,DEFAULT_CAPACITY 指在未定义 ArrayList大小的情况下,初始化 elementData 的长度为10
elementData 是 ArrayList 在存储数据时的 buffer,通过数组存储数据。同时,elementData 被 transient 修饰,所以在 ArrayList 序列化的时候,elementData 并不参与,而序列化的过程主要通过 writeObject(),readObject()实现。
构造方法
1  | /**  | 
具体方法
查找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
32
33/**
 * 正序查找
 * 判断查询对象是否为null, 若是则正序查找第一个值为 null 的对象,返回索引号
 */
public int indexOf(Object o) {
    if (o == null) {
        for (int i = 0; i < size; i++)
            if (elementData[i]==null)
                return i;
    } else {
        for (int i = 0; i < size; i++)
            if (o.equals(elementData[i]))
                return i;
    }
    return -1;
}
/**
 * 逆序查找
 * 判断查询对象是否为null, 若是则逆序查找第一个值为 null 的对象,返回索引号
 */
public int lastIndexOf(Object o) {
    if (o == null) {
        for (int i = size-1; i >= 0; i--)
            if (elementData[i]==null)
                return i;
    } else {
        for (int i = size-1; i >= 0; i--)
            if (o.equals(elementData[i]))
                return i;
    }
    return -1;
}
拷贝1
2
3
4
5
6
7
8
9
10
11
12
13
14
15/**
 * 通过super.clone(), 获取 ArrayList 的一个副本,
 * 再设置 ArrayList 的 elementData 和 modCount 属性。因为拷贝的是新的副本,将新副本的 modCount 设为0。
 */
public Object clone() {
    try {
        ArrayList<?> v = (ArrayList<?>) super.clone();
        v.elementData = Arrays.copyOf(elementData, size);
        v.modCount = 0;
        return v;
    } catch (CloneNotSupportedException e) {
        // this shouldn't happen, since we are Cloneable
        throw new InternalError(e);
    }
}
在拷贝的过程中,发现它调用了Arrays.copoOf(original, lenght),而Arrays.copy()又调用了System.arraycopy()1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18@SuppressWarnings("unchecked")
public static <T> T[] copyOf(T[] original, int newLength) {
    return (T[]) copyOf(original, newLength, original.getClass());
}
/**
 *  这里的又调用了System.arraycopy()
 */ 
public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
    @SuppressWarnings("unchecked")
    T[] copy = ((Object)newType == (Object)Object[].class)
        ? (T[]) new Object[newLength]
        : (T[]) Array.newInstance(newType.getComponentType(), newLength);
    System.arraycopy(original, 0, copy, 0,
                     Math.min(original.length, newLength));
    return copy;
}
System.arraycopy()是个 本地方法,底层调用了 c++ 方法实现,使其的效率更高1
2
3public static native void arraycopy(Object src,  int  srcPos,
                                        Object dest, int destPos,
                                        int length);
转化为数组1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17/**
 * 返回 elementData 的副本
 */
public Object[] toArray() {
    return Arrays.copyOf(elementData, size);
}
@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
    if (a.length < size)
        // Make a new array of a's runtime type, but my contents:
        return (T[]) Arrays.copyOf(elementData, size, a.getClass());
    System.arraycopy(elementData, 0, a, 0, size);
    if (a.length > size)
        a[size] = null;
    return a;
}
获取,修改元素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
32
33/**
 * 通过索引,返回查询elementData 中的值,便于其他方法的操作
 */
@SuppressWarnings("unchecked")
E elementData(int index) {
    return (E) elementData[index];
}
// 数组越界检查
private void rangeCheck(int index) {
    if (index >= size)
        throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
/**
 *  先进行越界异常检查,判断 index < size 时,返回查询结果
 */
public E get(int index) {
    rangeCheck(index);
    return elementData(index);
}
/**
 * 一样,先进行越界检查,将新值替代为旧值,返回旧值
 */
 public E set(int index, E element) {
    rangeCheck(index);
    E oldValue = elementData(index);
    elementData[index] = element;
    return oldValue;
}
移除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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51/**
 *  通过索引值删除
 *  System.arraycopy()将 elementData 的索引值后的元素向前移动,最后删除最后重复的元素值,size -1
 */
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;
}
/**
 *  通过对象值删除
 *  正序删除,当查找到要删除的值时,调用 fastRemove() 实现删除的具体操作
 */
public boolean remove(Object o) {
    if (o == null) {
        for (int index = 0; index < size; index++)
            if (elementData[index] == null) {
                fastRemove(index);
                return true;
            }
    } else {
        for (int index = 0; index < size; index++)
            if (o.equals(elementData[index])) {
                fastRemove(index);
                return true;
            }
    }
    return false;
}
/**
 *  fastRemove() 相比于 remove(): 跳过 rangeCheck() 越界检查 和 不返回删除值,这样可以更快得删除元素
 */
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
}
清除
1  | /**  | 
添加
1  | /**  | 
扩容机制 (扩容机制在jdk 1.7开始做出了改动,主要改动:采用 位运算 替代之前的操作符, 加入 最大数组容量 的判断)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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64/**
 *  当需要的 容量空间 大于 默认容量,执行ensureExplicitCapacity(minCapacity)
 */
public void ensureCapacity(int minCapacity) {
    int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
        // any size if not default element table
        ? 0
        // larger than default for default empty table. It's already
        // supposed to be at default size.
        : DEFAULT_CAPACITY;
    if (minCapacity > minExpand) {
        ensureExplicitCapacity(minCapacity);
    }
}
private void ensureCapacityInternal(int minCapacity) {
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    ensureExplicitCapacity(minCapacity);
}
/**
 *   modcount+1
 *   需求容量 大于 数组的大小时,执行grow()
 */
private void ensureExplicitCapacity(int minCapacity) {
    modCount++;
    // overflow-conscious code
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}
/**
 *  扩容的具体方法
 *  oldCapacity + ( oldCapacity >> 1) 位运算向右移一位,使得oldCapacity 为原来的1.5倍
 *  当 newCapacity 大于数组的最大长度时,调用hugeCapacity()调整
 *  拷贝新的 elementData 副本
 */
private void grow(int minCapacity) {
    // overflow-conscious code
    int oldCapacity = elementData.length;
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    // minCapacity is usually close to size, so this is a win:
    elementData = Arrays.copyOf(elementData, newCapacity);
}
/**
 *  调整容量
 */
private static int hugeCapacity(int minCapacity) {
    if (minCapacity < 0) // overflow
        throw new OutOfMemoryError();
    return (minCapacity > MAX_ARRAY_SIZE) ?
        Integer.MAX_VALUE :
        MAX_ARRAY_SIZE;
}
序列化(序列化的过程是将size, elementData中的所有对象写入或者读取),不采用将整个elementData写入是因为节省空间
1  | /**  | 
排序 (ArrayList的排序采用的是Array的并归排序)
1  | /**  |