ArrayList 實現 List 介面,底層由動態陣列 (Object[]) 支撐。核心特性:
get(i)/set(i,e) 為 O(1)。add(e) 平均常數時間。System.arraycopy)。Collections.synchronizedList / CopyOnWriteArrayList。ConcurrentModificationException,僅用於檢測 Bug,不可依賴於業務邏輯。private static final int DEFAULT_CAPACITY = 10; // 默認初始容量
private static final Object[] EMPTY_ELEMENTDATA = {}; // 空陣列實例 (延遲初始化用)
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; // JDK 8+ 区分显式0与默认
transient Object[] elementData; // 核心存儲陣列,transient 避免默認序列化 (自定義 writeObject/readObject)
private int size; // 實際元素個數 (非陣列長度)
疑問解答:
transient:elementData 可能未滿 (容量 > size),默認序列化會浪費空間且洩漏內部結構。ArrayList 自定義 writeObject 僅序列化 size 個有效元素。size vs length:陣列長度 = 容量 (capacity),通常 ≥ size。size 追蹤邏輯大小,支援 isEmpty()、邊界檢查等。// 1. 指定初始容量:避免擴容開銷,預知大概數據量時強烈建議使用
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);
}
// 2. 無參構造:延遲初始化,首次 add 時才分配 DEFAULT_CAPACITY (10)
public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; }
// 3. 集合轉換:toArray() 可能返回非 Object[],需防禦性複製修正類型
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
if ((size = elementData.length) != 0 && elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
}
public boolean add(E e) {
ensureCapacityInternal(size + 1); // 確保容量
elementData[size++] = e; // 賦值並遞增 size
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++; // 結構修改計數器,支援 fail-fast
if (minCapacity - elementData.length > 0)
grow(minCapacity); // 觸發擴容
}
// 核心擴容邏輯:新容量 = 舊容量 + 舊容量 >> 1 (即 1.5 倍)
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);
}
關鍵點:1.5 倍增長 (JDK 6/7 為 1.5 倍 + 1,JDK 8+ 為 1.5 倍) 平衡空間浪費與擴容頻次;Arrays.copyOf 底層調用 System.arraycopy (native),極高效。
ensureCapacity(int minCapacity):公開 API,批量添加前預分配,避免多次擴容複製。僅在元素已存在時有效 (空陣列時內部邏輯會調整為默認容量)。trimToSize():將容量壓縮至 size,釋放未使用記憶體,適合「不再新增、長期持有」場景。迭代器持有 expectedModCount = modCount 快照。每次 next()、remove() 前檢查 modCount == expectedModCount,不等則拋 ConcurrentModificationException。注意:非同步並發修改下無法保證 100% 檢測到,僅作調試輔助。
new ArrayList<>(estimatedSize)。LinkedList (但隨機訪問極慢) 或業務重構。CopyOnWriteArrayList (讀多寫少) 或外部鎖 / 並發容器。