1.结构简介
- ArrayList实现了List接口,继承了AbstractList抽象类;
- 底层实基于Object数组实现容量大小动态变化;
- 允许null值存在;
- 同时还实现了RandomAccess,Cloneable,Serializable接口,所以ArrayList支持快速访问、复制、序列化。
2.成员变量
private static final int DEFAULT_CAPACITY = 10; //数组默认初始容量
private static final Object[] EMPTY_ELEMENTDATA = {}; //指定初始容量为0时的实例对象
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; //空参的实例对象
private transient Object[] elementData; //数组
private int size; //当前数组包含元素数
AbstractList中有个modCount参数:记录List操作次数,使用在Iterator,防止迭代过程中集合被修改。
3.构造方法
- 构造一个空列表
public ArrayList() {
this.elementData = 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);
}
}
- 构造一个包含指定集合元素的列表
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;
}
}
4.扩容
4.1 源码
add(E e)
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
ensureCapacityInternal(int minCapacity)
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
ensureExplicitCapacity(int minCapacity)
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
grow(int minCapacity)
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);
}
4.2 源码分析
4.3 总结
- 若是无参初始化ArrayList,首次add后数组容量会变更为DEFAULT_CAPACITY=10。
- 当add后的size(即size+1)大于当前数组长度时,则会进行1.5倍[算法公式:length+(length>>1)]扩容。
- 扩容的容量大小必须在add后size(即size+1)与MAX_ARRAY_SIZE之间。
- 扩容时是使用Arrays.copyof()新建一个容量数组,原数组被GC回收。
5.版本差异
5.1 new ArrayList()初始化差异
- JDK1.6及之前:初始容量为10的数组对象。
- JDK1.7:elementData=EMPET_ELEMENTDATE({})初始容量为0;首次add时再懒初始化至10。
- JDK1.8:elementData=DEFAULT_EMPTY_ELEMENTDATA({})初始容量为0;首次add时再懒初始化至10。
区别于jdk1.7,ArrayList()时,赋值的是DEFAULTCAPACITY_EMPTY_ELEMENTDATA空数组对象, ArrayList(0)时赋值的是EMPTY_ELEMENTDATA空数组对象。这么代码是为了ArrayList(0)能重用空数组常量EMPTY_ELEMENTDATA,减少new Object[0]操作,降低内存消耗。
JDK1.7:
public ArrayList(int initialCapacity) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
this.elementData = new Object[initialCapacity];
}
JDK1.8:
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);
}
}
5.2 扩容差异
- JDK1.6及之前: (length*3)/2+1
- JDK1.7及之后:length+(length>>1) [>>1相比/2:速度快,而且占用资源少,也避免过早出现int溢出的情况。]