ArrayList 源码学习第一季
继承实现
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
// 忽略其他内容
}
从上图我们即可得知,它实现了四个接口: List<E>
, RandomAccess
, Cloneable
, java.io.Serializable
; 以及继承了 AbstractList<E>
.
那么这四个接口分别是干什么的呢?
-
List: List 相关接口,不用多做介绍 -
RandomAccess: 支持快速随机访问, 所在包: java.util
-
Cloneable: 支持对象克隆, 所在包: java.lang
-
Serializable: 序列化接口, 所在包: java.io
另外 AbstractList 这个类中定义了一些 List 的公共方法.
成员变量
/**
* 默认的初始容量
*/
private static final int DEFAULT_CAPACITY = 10;
/**
* 用于空实例的共享空数组实例
*/
private static final Object[] EMPTY_ELEMENTDATA = {};
/**
* 用于默认大小的空实例的共享空数组实例。我们将此与 EMPTY_ELEMENTDATA 区分开来,以了解在添加第一个元素时要膨胀多少
*/
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
/**
* 存储 ArrayList 元素的数组缓冲区。 ArrayList 的容量就是这个数组缓冲区的长度。 * 当添加第一个元素时,任何带有 elementData == DEFAULTCAPACITY_EMPTY_ELEME * NTDATA的空 ArrayList 都将扩展为 DEFAULT_CAPACITY
*/
transient Object[] elementData; // non-private to simplify nested class access
/**
* ArrayList 的大小(它包含的元素数量)。
*/
private int size;
注意点
-
EMPTY_ELEMENTDATA
和DEFAULTCAPACITY_EMPTY_ELEMENTDATA
虽然这两个都是空数组,但不同在于 DEFAULTCAPACITY_EMPTY_ELEMENTDATA
是可以扩容的,当有元素被添加到数组中时,DEFAULTCAPACITY_EMPTY_ELEMENTDATA
会扩容到 DEFAULT_CAPACITY
定义的大小;
ArrayList
初始化时可以选择传入初始大小,不传的话就会使用默认的 DEFAULTCAPACITY_EMPTY_ELEMENTDATA
,建议创建时显示赋值。
构造方法
代码如下:
/**
* 构造一个具有指定初始容量的空列表
*/
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);
}
}
/**
* 构造一个初始容量为 10 的空列表
*/
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
/**
* 构造一个包含指定 collection 的元素的数组,元素的顺序是 collection 的迭代器返回的顺序
*
*/
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
if ((size = elementData.length) != 0) {
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// replace with empty array.
this.elementData = EMPTY_ELEMENTDATA;
}
}
事实上在实际使用过程中我们最常用的是无参的构造方法,但是如果可以预估出数组的大小,也可以传入一个预估的值,减少扩容的时间和内存消耗。
- END -