首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

Java 容器源码分析之 ArrayList(1)

Java 容器源码分析之 ArrayList(1)

概览ArrayList是最常使用的集合类之一了。在JDK文档中对ArrayList的描述是:ArrayList是对list接口的一种基于可变数组的实现。ArrayList类的声明如下:
1
2
public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
ArrayList继承了AbstractList抽象类,并实现了List,RandomAccess,Cloneable以及Serializable接口。对 RandomAccess 接口的实现表明支持随机访问(因为基于数组嘛~),同Cloneable接口和Serializable接口一样,该接口只是一个标记,不需要实现任何方法。ArrayList 可以支持值为 null 的元素。
本文中的分析都是针对JDK8中的源码进行的。
底层结构从文档中的说明可以知道,ArrayList的底层是基于数组来实现的。那我们就先来看一下ArrayList的成员变量:
1
2
3
4
5
6
7
8
9
10
11
private static final long serialVersionUID = 8683452581122892189L;

private static final int DEFAULT_CAPACITY = 10;
private static final Object[] EMPTY_ELEMENTDATA = {};
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

//The maximum size of array to allocate.
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

transient Object[] elementData;
private int size;
使用了一个 Object 数组来存放数据,并维护一个计对数器来记录当前容器中元素的数量。注意到数组 elementData 是使用 transient 来修饰的,在后面会此进行进行解释。
除此以外,在 ArrayList 还有一个继承自父类 AbstractList 的成员变量 modCount 需要关注。使用 modCount 记录列表发生结构化修改的次数,从而提供 fail-fast 的迭代器。因为 ArrayList 的实现是非同步的,如果在迭代过程中另一个线程向同一个容器中添加元素或移除元素,就会导致ConcurrentModificationExceptions。
1
2
//The number of times this list has been structurally modified.
protected transient int modCount = 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
/**
* Constructs an empty list with the specified initial 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);
    }
}

/**
* Constructs an empty list with an initial capacity of ten.
*/
public ArrayList() {
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

/**
* Constructs a list containing the elements of the specified
* collection, in the order they are returned by the collection's
* iterator.
*/
public ArrayList(Collection<? extends E> c) {
    elementData = c.toArray();
    if ((size = elementData.length) != 0) {
        // c.toArray might (incorrectly) not return Object[]
        if (elementData.getClass() != Object[].class)
            elementData = Arrays.copyOf(elementData, size, Object[].class);
    } else {
        // replace with empty array.
        this.elementData = EMPTY_ELEMENTDATA;
    }
}
ArrayList 类提供了三个构造方法,如上所示。除了初始化一个空的ArrayList以外,还支持使用另外一个容器中的元素来初始化ArrayList。注意到,在初始化一个空的ArrayList时,如果不指定容量的大小,默认容量是10。在初始化一个空的ArrayList时,如果指定容量为0,则数组引用指向的是一个静态成员变量EMPTY_ELEMENTDATA;如果使用默认容量,则数组引用指向的是一个静态成员变量DEFAULTCAPACITY_EMPTY_ELEMENTDATA;除此以外,按照实际指定的容量分配数组空间。
返回列表