public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
基本属性
-
基于数组实现
-
支持快速随机访问
-
数组默认大小为10
private static final int DEFAULT_CAPACITY = 10;
扩容操作
添加元素,add()方法
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
1.调用ensureCapacityInternal()
确保容量足够:
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(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);
}
2.如果list的容量不够,会调用grow()
扩容,新的容量是旧的容量的1.5倍
int newCapacity = oldCapacity + (oldCapacity >> 1);
从grow()
方法的最后一行:
elementData = Arrays.copyOf(elementData, newCapacity);
将就数组的赋值给新数组,这个操作在list长度很长的时候 造成的系统开销很高,所以最好在创建集合时,就指定长度,避免集合频繁的扩容。
删除操作
ArrayList的删除元素的方法 remove(int index)
:
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;
}
1.首先rangeCheck(index)
检查 index 是否合法,越界
2.将集合 index+1及以后的元素 复制到 集合 index的位置及以后,这样就把 index上原有的元素覆盖掉了。
3.elementData[--size] = null
集合最后一位设为 null ,并长度 -1。
fail-fast 机制
Fail fast
是 Java 集合中 一种错误检测机制,当多个线程对集合进行结构上的改变(添加或者删除至少一个元素)的操作时,程序很可能抛出 ConcurrentModificationException
错误,是很可能,不是一定。
在ArrayList中,modCount用来记录 结构发生变化的次数,在进行序列化或者迭代等(正常进行不会引起结构发生改变)操作时,需要比较操作前后modCount
是否改变,若发生改变,则抛出异常ConcurrentModificationException
.