简介
ArrayList是一个可变数组,内部封装一个Object[]数组用于存放元素。
删除
删除动作都是通过public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length);
接口完成的。其中removeAll
和retainAll
的算法是先将要保留的元素放到数组的头部,然后在通过arrayCopy
完成。具体代码如下:
private boolean batchRemove(Collection<?> c, boolean complement) {
final Object[] elementData = this.elementData;
int r = 0, w = 0;
boolean modified = false;
try {
for( ; r < size; r++)
if((c.contains(elementData[r]) == complement)
elementData[w++] = elementData[r];
} finally {
if(r != size) {
System.arrayCopy(elementData, r, elementData, w, size - r);
w += size - r;
if(w != size) {
for(int i = w; i < size; i++)
elementData[i] = null;
modCount += size - w;
size = w;
modified = true;
}
}
return modified;
}
其中,complement
为true
的时候用于retainAll
,为false
用removeALl
。执行removeAll
时,contains
抛出异常, 返回值为false。
增加元素时动态扩容
首先看ArrayList的域变量:
private static final int DEFAULT_CAPACITY = 10;
private static final Object[] EMPTY_ELEMENTDATA = {};
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
transient Object[] elementData;
private int size;
其中,创建ArrayList
且未指定容量大小时,用DEFAULTCAPACITY_EMPTY_ELEMENTDATA
初始化elementData
。当创建ArrayList
且指定容量为0时,用EMPTY_ELEMENTDATA
初始化elementData
。
除了ArrayList(Collection<? extends E> c)
之外,通过两外两种方式创建的对象,都只会在第一次add的时候分配内存空间。
扩容代码
private void grow(int minCapacity) {
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0 )
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
}
其中,用到了Arrays
类的copyOf
方法创建新的数组并将原有元素拷贝,如果新数组容量大于原有数组容量,新增加的位置将会初始化为0或null。
public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
T[] copy = ((Object) newType == (Object)Object.class) ? (T[] new Object[newLength] : (T[] Arrays.newInstance(newType.getComponentType, newLength);
System.arrayCopy(original, 0, copy, 0, Math.min(original.length, newLength));
return copy;
}
另外,还可以通过ensureCapacity(int minCapacity)
主动扩容。
缩容
ArrayList
中size
用于表示当前数组中元素的个数,当size
小于数组长度length
时,可以通过trimToSize
缩减存储占用。
public void trimToSize() {
modCount++;
if(size < elementData.length) {
elementData = (size == 0) ? EMPTY_ELEMNTDATA : Arrays.copyOf(elementData, size);
}
}
迭代器
ArrayList
成员变量int modCount
用于保存所有对ArrayList
修改的次数。这个值被Iterator
和ListIterator
用来判断使用迭代器的过程中是否存在同步更改ArrayList
的情况。
ArrayList
支持两种迭代器,一种实现了接口Iterator
,另一种实现了ListIterator
。前者用于遍历和删除,后者用于插入、双向遍历和删除。