声明
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable
实现了序列化和克隆接口,RandomAccess
是随机访问接口
基本参数
// default capacity
private static final int DEFAULT_CAPACITY = 10;
// 空实例的共享空数组实例。
private static final Object[] EMPTY_ELEMENTDATA = {};
// 无参构造函数的空数组使用 DEFAULTCAPACITY_EMPTY_ELEMENTDATA
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
// 存储ArrayList元素的数组缓冲区
// ArrayList的容量是此数组的长度
transient Object[] elementData; // non-private to simplify nested class access
// Arraylist包含的元素数量
private int size;
size
表示ArrayList
的实际大小,注意数组元素均为Object
类型
三种构造函数
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
// 有参构造下,initialCapacity为零会使用 EMPTY_ELEMENTDATA
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity);
}
}
public ArrayList() { // 无参构造,使用 DEFAULTCAPACITY_EMPTY_ELEMENTDATA 赋给 elementData
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
public ArrayList(Collection<? extends E> c) {
// c.toArray在很多地方都这样用过。。
Object[] a = c.toArray();
if ((size = a.length) != 0) {
// a的大小不为零,且集合c的类型是ArrayList,直接让elementData指向a即可
if (c.getClass() == ArrayList.class) {
elementData = a;
} else {
elementData = Arrays.copyOf(a, size, Object[].class);
}
} else {
// replace with empty array.
elementData = EMPTY_ELEMENTDATA;
}
}
Arrays.copyOf
内部调用的是System.arraycopy
函数,
System.arraycopy(Object src, int srcPos,Object dest, int destPos,int length);
// src:源数组,srcPos原数组的起点
// dest:目的数组,destPos目的数组的起点
基本方法
add
(1) 添加到末尾
// Attention: @return: boolean
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Incre modCount. 实际modCount++在 ensureExplicitCapacity函数中,来自AbstractList,fail-fast机制
elementData[size++] = e;
return true;
}
(2) 插入到指定的位置
public void add(int index, E element) {
rangeCheckForAdd(index);
ensureCapacityInternal(size + 1); // Increments modCount!!
System.arraycopy(elementData, index, elementData, index + 1, size - index); // 注意是size减去index
elementData[index] = element;
size++;
}
remove
(1) 删除指定位置的元素
利用System.arraycopy
前移动index
之后的元素一个,然后将末尾设为null
即可
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;
}
(2) 删除对应的值
public boolean remove(Object o) {
if (o == null) {
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index); // fastRemove逻辑跟上面一样
return true;
}
}
return false;
}
clear:
public void clear() {
modCount++;
// clear to let GC do its work
for (int i = 0; i < size; i++)
elementData[i] = null;
size = 0;
}
其它方法:
addAll(Collection<? extends E> c);
addAll(int index, Collection<? extends E> c);
removeRange(int fromIndex, int toIndex);
// 上述三个跟常规的add、remove逻辑类似。
removeAll(Collection<?> c);
其中removeAll
使用了batchRemove
函数:batchRemove
函数使用try···catch
来捕获异常。
public boolean removeAll(Collection<?> c) {
Objects.requireNonNull(c);
return batchRemove(c, false);
}
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++)
// complement是false,该行会找到那些不在 Collection的元素,然后覆盖到 w 位置上
if (c.contains(elementData[r]) == complement)
elementData[w++] = elementData[r];
} finally {
// c.contains(elementData[r]的c是Collection类型, 可能会抛出异常, 导致无法处理完, 此时r!=size, 所以需要把r右侧的元素保留下来.
if (r != size) {
System.arraycopy(elementData, r,
elementData, w,
size - r);
w += size - r;
}
if (w != size) {
// clear to let GC do its work
for (int i = w; i < size; i++)
elementData[i] = null;
modCount += size - w;
size = w;
modified = true;
}
}
return modified;
}
序列化和反序列化:因为elementdata
被transient
修饰,因此使用 writeObject()
和 readObject()
来控制只序列化数组中有元素填充的那部分内容
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException{
int expectedModCount = modCount;
s.defaultWriteObject(); // 此方法将当前类的非静态和非瞬态字段写入此流。
s.writeInt(size); // 写入size
for (int i=0; i<size; i++) {
s.writeObject(elementData[i]);
}
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
}
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
elementData = EMPTY_ELEMENTDATA;
// Read in size, and any hidden stuff
s.defaultReadObject();
// Read in capacity
s.readInt(); // ignored
if (size > 0) {
int capacity = calculateCapacity(elementData, size); //
SharedSecrets.getJavaOISAccess().checkArray(s, Object[].class, capacity);
ensureCapacityInternal(size);
Object[] a = elementData;
// Read in all elements in the proper order.
for (int i=0; i<size; i++) {
a[i] = s.readObject();
}
}
}
SubList类:
- 对子SubList的增删导致原List的数据变化
- 对原List的增删会导致子SubList的的操作抛出并发修改异常
public List<E> subList(int fromIndex, int toIndex) {
subListRangeCheck(fromIndex, toIndex, size);
return new SubList(this, 0, fromIndex, toIndex);
}
private class SubList extends AbstractList<E> implements RandomAccess {
private final AbstractList<E> parent;
private final int parentOffset;
private final int offset;
int size;
SubList(AbstractList<E> parent,
int offset, int fromIndex, int toIndex) {
this.parent = parent;
this.parentOffset = fromIndex;
this.offset = offset + fromIndex;
this.size = toIndex - fromIndex;
this.modCount = ArrayList.this.modCount;
}
// ...
}
扩容机制
ArrayList
在add
的时候会调用ensureExplicitCapacity
去判断当前容量是否足够:
// add
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity); // 容量不够的时候执行grouw函数扩容
}
grow
函数
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1); // 扩大到原来的1.5倍
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity; // 扩大到1.5倍仍不够就扩大到minCapacity
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// Array.copyOf( T[] original, int newLength);
elementData = Arrays.copyOf(elementData, newCapacity);
}