ArrayList 以 Object[] elementData 為底層存儲,實現所有 List 操作,允許 null。與 Vector 幾乎方法級同步不同,ArrayList 僅在 writeObject/readObject 同步,性能優勢顯著。
private static final long serialVersionUID = 8683452581122892189L;
private transient Object[] elementData; // transient:不自動序列化
private int size; // 邏輯大小
transient 關鍵:陣列持有的是對象引用而非對象本身,直接序列化引用無意義,需手工序列化實際元素。
public boolean add(E e) {
ensureCapacityInternal(size + 1); // 確保容量
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); // 默認 10
}
ensureExplicitCapacity(minCapacity);
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
private void grow(int minCapacity) {
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1); // 1.5 倍
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
}
關鍵點:
{},首次 add 才分配默認 10 容量(延遲分配)old + old/2 平衡了內存浪費與擴容頻次Arrays.copyOf 為 native 實現,高效複製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; // 清除引用,助力 GC
return oldValue;
}
System.arraycopy 為 native 方法,同陣列複製時內部使用臨時緩衝,安全高效。
modCount 記錄結構性修改次數(add/remove/clear 等均增 1)。
// AbstractList 內部類
private class Itr implements Iterator {
int cursor, lastRet = -1;
int expectedModCount = modCount; // 快照
public boolean hasNext() { return cursor != size; }
public E next() {
checkForComodification();
int i = cursor;
if (i >= size) throw new NoSuchElementException();
cursor = i + 1;
return elementData(lastRet = i);
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
設計哲學:不加鎖、不複製、以「版本號比對」極低成本檢測並發修改,發現即拋異常——快速失效。
private void writeObject(ObjectOutputStream s) throws IOException {
int expectedModCount = modCount;
s.defaultWriteObject(); // 寫入 size 等非 transient 字段
s.writeInt(elementData.length); // 寫入陣列長度(保留容量信息)
for (int i = 0; i < size; i++)
s.writeObject(elementData[i]); // 逐個序列化元素
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {
s.defaultReadObject();
int arrayLength = s.readInt();
elementData = new Object[arrayLength];
for (int i = 0; i < size; i++)
elementData[i] = s.readObject();
}
亮點:
capacity(陣列長度),反序列化後無需立即擴容modCount 變化,防止併發修改導致數據不一致synchronized 保證序列化過程原子性| 場景 | 推薦 | 理由 |
|---|---|---|
| 單線程/線程封閉 | ArrayList | 零同步開銷,擴容策略優秀 |
| 多線程讀多寫少 | CopyOnWriteArrayList | 讀無鎖,寫複製,適合觀察者模式 |
| 多線程讀寫均衡 | Collections.synchronizedList / Vector | 方法級鎖,簡單但擴展性差 |
| 高併發隊列 | ConcurrentLinkedQueue | 無鎖 CAS,吞吐量最高 |