黑马程序员技术交流社区

标题: 【上海校区】【Java8源码】ArrayList源码分析 [打印本页]

作者: 不二晨    时间: 2018-12-31 09:59
标题: 【上海校区】【Java8源码】ArrayList源码分析
继承关系

ArrayList继承关系

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
1
2
AbstractList继承关系

public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E>
1
List继承关系

public interface List<E> extends Collection<E>
1
AbstractCollection继承关系

public abstract class AbstractCollection<E> implements Collection<E>
1
Collection继承关系

public interface Collection<E> extends Iterable<E>
1
相关接口和类

Iterable接口:实现该接口的类就可以使用for (Suit suit : suits)来遍历
Collection接口:集合类的根接口
AbstractCollection类:提供Collection接口的基础实现,最大限度地减少实现此接口所需的工作量
List接口:有序集合、允许重复元素、允许空元素、控制元素的插入位置、通过索引访问元素、在列表里搜索元素。扩展了Collection接口,添加一些额外方法
AbstractList类:提供List接口的基础实现,以最大限度地减少随机访问列表(数组)实现此接口所需的工作量
RandomAccess接口:标记接口,说明支持随机访问
Cloneable接口:可以调用clone方法进行对象的克隆
Serializable接口:可序列化
关于ArrayList

可调整大小
不是线程安全的
iterator() 和 listIterator() 支持快速失败机制
字段

fields

父类AbstractList:
    // 列表在结构上被改变的次数,结构改变是指列表大小改变或以其他方式的改变,可能使得正在进行的迭代产生不正确的结果
    protected transient int modCount = 0;

子类ArrayList:
    private static final long serialVersionUID = 8683452581122892189L;

    // 默认的capacity,capacity是elementData的大小,size是ArrayList的大小
    private static final int DEFAULT_CAPACITY = 10;

    // 调用ArrayList(0)会指向这个数据,第一次进行add时,capacity变为1(假设第一次add之前不包括其他任何操作)
    private static final Object[] EMPTY_ELEMENTDATA = {};

    // 调用ArrayList()是会指向这个数组,第一次进行add时,capacity变为10(假设第一次add之前不包括其他任何操作)
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

    // 元素存储的地方,也是ArrayList的数据结构,用一个Object数组来存元素
    transient Object[] elementData; // 非私有的,简化嵌套类的访问

    // size是ArrayList的大小,也就是elementData中实际存入元素的大小
    // capacity是elementData实际大小,capacity是大于等于size的
    private int size;

    // elementData最大被分配的大小
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
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
构造函数

constructors

    // 参数是capacity
    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);
        }
    }

    // 无参数的
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

    // 参数是集合的
    public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray(); // Object[] toArray(); 返回一个新分配的对象数组,包含此集合的所有元素
        if ((size = elementData.length) != 0) {
            // c.toArray might (incorrectly) not return Object[] (see 6260652)
            // (coll) Arrays.asList(x).toArray().getClass() should be Object[].class
            // Arrays.asList(x).toArray().getClass()返回的class类型不一定是Object[].class
            if (elementData.getClass() != Object[].class)
                elementData = Arrays.copyOf(elementData, size, Object[].class); // 关于数组的复制,见下面
        } else {
            // 指向空数组
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

数组复制函数如下:
System类:
    // src是源数组、srcPos源数组开始的位置、dest是目的数组、destPos是目的数组开始的位置、length是元素复制的长度
    // 如果src和dest是同一个引用,复制的时候,会把这个数组先复制到一个临时数组,然后在从临时数组复制到这个数组
    public static native void arraycopy(Object src,  int  srcPos,
                                        Object dest, int destPos,
                                        int length);

Arrays类:
    // 新建一个数组,调用System.arraycopy(Object, int, Object, int, int),把原数组复制到新数组,返回新数组
    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;
    }

    // 调用Arrays.copyOf(U[], int, Class<? extends T[]>)函数,class类型是原数组的类型
    public static <T> T[] copyOf(T[] original, int newLength) {
        return (T[]) copyOf(original, newLength, original.getClass());
    }
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
相关方法

capacity和size

capacity

    // 把capacity变成和size一样大
    public void trimToSize() {
        modCount++;
        if (size < elementData.length) {
            elementData = (size == 0)
              ? EMPTY_ELEMENTDATA
              : Arrays.copyOf(elementData, size);
        }
    }

    // 改变列表的capacity,使用者调用,可以避免不必要的自动扩容
    public void ensureCapacity(int minCapacity) {
        int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
            ? 0
            : DEFAULT_CAPACITY;

        if (minCapacity > minExpand) {
            ensureExplicitCapacity(minCapacity);
        }
    }

    // 改变列表的capacity,类内部调用
    private void ensureCapacityInternal(int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }

        ensureExplicitCapacity(minCapacity);
    }
       
        // modCount加1,检查是否真正的需要扩容
    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); // capacity增长的比例,不是严格的1.5倍
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);

        elementData = Arrays.copyOf(elementData, newCapacity);
    }

    // 计算capacity的最大值
    private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }
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
size

    // 返回size的大小
    public int size() {
        return size;
    }

    // 列表是否为空
    public boolean isEmpty() {
        return size == 0;
    }
1
2
3
4
5
6
7
8
9
增删改查

add

    // 先检查是否需要扩充容量,添加元素,size加1
    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }

    // 检查位置是否越界,然后检查是否需要扩容
    // 再原数组上把index后面(包括index)的元素后移一位,然后设置index上的元素,size加1
    public void add(int index, E element) {
        rangeCheckForAdd(index);

        ensureCapacityInternal(size + 1);  // Increments modCount!!
        System.arraycopy(elementData, index, elementData, index + 1,
                         size - index);
        elementData[index] = element;
        size++;
    }

    // 先检查是否需要扩容,再把c的所有元素复制到原数组的size后面(包括size),size加c.size()
    public boolean addAll(Collection<? extends E> c) {
        Object[] a = c.toArray();
        int numNew = a.length;
        ensureCapacityInternal(size + numNew);  // Increments modCount
        System.arraycopy(a, 0, elementData, size, numNew);
        size += numNew;
        return numNew != 0;
    }

    // 检查位置是否越界,检查是否需要扩容
    // 再原数组上把index后面(包括index)的元素后移c.size()位,然后设置index上的元素
    // 在把c的所有元素复制到原数组index后面(包括index)
    // size加c.size()
    public boolean addAll(int index, Collection<? extends E> c) {
        rangeCheckForAdd(index);

        Object[] a = c.toArray();
        int numNew = a.length;
        ensureCapacityInternal(size + numNew);  // Increments modCount

        int numMoved = size - index;
        if (numMoved > 0)
            System.arraycopy(elementData, index, elementData, index + numNew,
                             numMoved);

        System.arraycopy(a, 0, elementData, index, numNew);
        size += numNew;
        return numNew != 0;
    }
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
get

    // 位置访问操作
    E elementData(int index) {
        return (E) elementData[index];
    }

    // 检查是否越界,然后取元素
    public E get(int index) {
        rangeCheck(index);

        return elementData(index);
    }

    // 列表是否包含对象o
    public boolean contains(Object o) {
        return indexOf(o) >= 0;
    }

    // 列表中第一次出现对象o的位置,找到就立刻返回,找不到返回-1
    // 使用的是元素的equals方法
    public int indexOf(Object o) {
        if (o == null) {
            for (int i = 0; i < size; i++)
                if (elementData==null)
                    return i;
        } else {
            for (int i = 0; i < size; i++)
                if (o.equals(elementData))
                    return i;
        }
        return -1;
    }

    // 列表中最后一次出现对象o的位置,找到就立刻返回,找不到返回-1
    // 使用的是元素的equals方法
    public int lastIndexOf(Object o) {
        if (o == null) {
            for (int i = size-1; i >= 0; i--)
                if (elementData==null)
                    return i;
        } else {
            for (int i = size-1; i >= 0; i--)
                if (o.equals(elementData))
                    return i;
        }
        return -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
34
35
36
37
38
39
40
41
42
43
44
45
46
set

    // 检查是否越界,设置元素,返回老元素
    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
remove

    // 检查位置是否越界,在原数组上把index后面(不包括index)的元素向前移动一位
    // 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;
    }

    // 查找是否存在o,如果存在就调用fastRemove(int)方法,返回true
    // 否则返回false
    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;
    }

    // 跟remove(int)差不多,就是去掉了越界检查和返回值
    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
    }

    // 将数组清空
    public void clear() {
        modCount++;

        // clear to let GC do its work
        for (int i = 0; i < size; i++)
            elementData = null;

        size = 0;
    }

    // 把toIndex(包括toIndex)后的元素向前移动(toIndex-fromIndex)位
    protected void removeRange(int fromIndex, int toIndex) {
        modCount++;
        int numMoved = size - toIndex;
        System.arraycopy(elementData, toIndex, elementData, fromIndex,
                         numMoved);

        // clear to let GC do its work
        int newSize = size - (toIndex-fromIndex);
        for (int i = newSize; i < size; i++) {
            elementData = null;
        }
        size = newSize;
    }

    // 把c包含的元素都删除掉(前提是contains方法不抛错)
    public boolean removeAll(Collection<?> c) {
        Objects.requireNonNull(c);
        return batchRemove(c, false);
    }

    // 仅留下c包含的元素(前提是contains方法不抛错)
    public boolean retainAll(Collection<?> c) {
        Objects.requireNonNull(c);
        return batchRemove(c, true);
    }

    private boolean batchRemove(Collection<?> c, boolean complement) {
        final Object[] elementData = this.elementData;
        int r = 0, w = 0;
        boolean modified = false;
        try {
            for (; r < size; r++)
                if (c.contains(elementData[r]) == complement)
                    elementData[w++] = elementData[r];
        } finally {

            // 如果contains方法抛错了,抛错位置(包括此位置)后面的元素照样保留
            if (r != size) {
                System.arraycopy(elementData, r,
                                 elementData, w,
                                 size - r);
                w += size - r;
            }
            if (w != size) {
                // clear to let GC do its work
                for (int i = w; i < size; i++)
                    elementData = null;
                modCount += size - w;
                size = w;
                modified = true;
            }
        }
        return modified;
    }
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
rangeCheck

    private void rangeCheck(int index) {
        if (index >= size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

    private void rangeCheckForAdd(int index) {
        if (index > size || index < 0)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

    private String outOfBoundsMsg(int index) {
        return "Index: "+index+", Size: "+size;
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
toArray、iterator和subList

toArray

    // 返回一个新数组
    public Object[] toArray() {
        return Arrays.copyOf(elementData, size);
    }

    // 如果a.length小于size则返回elementData的copy
    // 否则,将elementData的元素直接复制到a中
    public <T> T[] toArray(T[] a) {
        if (a.length < size)
            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
iterator

    // 返回Iterator
    public Iterator<E> iterator() {
        return new Itr();
    }

    // 返回指定位置的ListIterator
    public ListIterator<E> listIterator(int index) {
        if (index < 0 || index > size)
            throw new IndexOutOfBoundsException("Index: "+index);
        return new ListItr(index);
    }

    // 返回第0位的ListIterator
    public ListIterator<E> listIterator() {
        return new ListItr(0);
    }


Iterator和listIterator都是ArrayList的私有内部类,继承结构如下:
private class Itr implements Iterator<E>
private class ListItr extends Itr implements ListIterator<E>
public interface ListIterator<E> extends Iterator<E>

Iterator是迭代器接口,ListIterator继承了Iterator,丰富了一些功能。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
subList

    // 返回的SubList,在SubList中所有的操作都是基于ArrayList.this来操作的
    public List<E> subList(int fromIndex, int toIndex) {
        subListRangeCheck(fromIndex, toIndex, size);
        return new SubList(this, 0, fromIndex, toIndex);
    }

    // 位置越界判断
    static void subListRangeCheck(int fromIndex, int toIndex, int size) {
        if (fromIndex < 0)
            throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
        if (toIndex > size)
            throw new IndexOutOfBoundsException("toIndex = " + toIndex);
        if (fromIndex > toIndex)
            throw new IllegalArgumentException("fromIndex(" + fromIndex +
                                               ") > toIndex(" + toIndex + ")");
    }

返回的SubList是ArrayList的私有内部类,继承关系如下:
private class SubList extends AbstractList<E> implements RandomAccess
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
sort、clone和序列化

sort

    // 调用Arrays的sort函数进行排序
    public void sort(Comparator<? super E> c) {
        final int expectedModCount = modCount;
        Arrays.sort((E[]) elementData, 0, size, c);
        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
        modCount++;
    }
1
2
3
4
5
6
7
8
9
clone

    // 克隆方法,克隆对象的elementData是一个新数组,属于浅拷贝
    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);
        }
    }
1
2
3
4
5
6
7
8
9
10
11
12
serialize

    // 序列化的写入操作会调用此方法
    private void writeObject(java.io.ObjectOutputStream s)
        throws java.io.IOException{
        // Write out element count, and any hidden stuff
        int expectedModCount = modCount;
        s.defaultWriteObject();

        // Write out size as capacity for behavioural compatibility with clone()
        s.writeInt(size);

        // Write out all elements in the proper order.
        for (int i=0; i<size; i++) {
            s.writeObject(elementData);
        }

        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
    }

    // 序列化的读操作会调用此方法
    private void readObject(java.io.ObjectInputStream s)
        throws java.io.IOException, ClassNotFoundException {
        elementData = EMPTY_ELEMENTDATA;

        // Read in size, and any hidden stuff
        s.defaultReadObject();

        // Read in capacity
        s.readInt(); // ignored

        if (size > 0) {
            // be like clone(), allocate array based upon size not capacity
            ensureCapacityInternal(size);

            Object[] a = elementData;
            // Read in all elements in the proper order.
            for (int i=0; i<size; i++) {
                a = s.readObject();
            }
        }
    }
---------------------
转载,仅作分享,侵删
原文:https://blog.csdn.net/qq_21687635/article/details/84976305



作者: 不二晨    时间: 2019-1-3 10:08
奈斯




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2