Java 容器源码分析之 ArrayList(1)
 
- UID
- 1066743
|

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;除此以外,按照实际指定的容量分配数组空间。 |
|
|
|
|
|