ArrayList 是 List 接口最常用的實現,底層由 動態數組 支撐。本文系統梳理其 字段定義、三種構造器、擴容機制、核心增刪改查方法、序列化處理,並給出演示代碼與性能建議,助你在面試與實戰中游刃有餘。
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; // 邏輯大小(元素個數)
transient:elementData 不參與默認序列化,ArrayList 自定義 writeObject/readObject 只序列化有效元素,節省空間;EMPTY_ELEMENTDATA 用於 new ArrayList(0),DEFAULTCAPACITY_EMPTY_ELEMENTDATA 用於無參構造,首次 add 時才擴容至 10,實現「延遲分配」。| 構造器 | 初始容量 | 適用場景 |
|---|---|---|
ArrayList() | 0(延遲至首次 add 擴容為 10) | 元素數量未知、較小 |
ArrayList(int initialCapacity) | 指定值(>0 分配數組,=0 用 EMPTY,<0 拋異常) | 能預估大致數據量,避免多次擴容拷貝 |
ArrayList(Collection<? extends E> c) | 集合大小 | 集合轉列表、合併數據 |
public void ensureCapacity(int minCapacity) {
int oldCapacity = elementData.length;
if (minCapacity > oldCapacity) {
int newCapacity = oldCapacity + (oldCapacity >> 1); // 1.5 倍
if (newCapacity < minCapacity) newCapacity = minCapacity;
elementData = Arrays.copyOf(elementData, newCapacity);
}
}
add(E e)、addAll() 等寫入方法均先調用 ensureCapacityInternal(size+1) 檢查擴容。add(E e):elementData[size++] = e,攤還 O(1);add(int index, E element):System.arraycopy(elementData, index, elementData, index+1, size-index) 向右移動,O(n);addAll(Collection c):轉數組後 System.arraycopy 一次性拷貝;addAll(int index, Collection c):先向右移動騰空間,再拷貝新數據。remove(int index):System.arraycopy(elementData, index+1, elementData, index, size-index-1) 向左移動,最後一位置 null 幫助 GC;remove(Object o):遍歷查找首個匹配項調用 fastRemove(index);removeRange(from, to):System.arraycopy 一次性前移,尾部置 null;AbstractCollection,迭代器調用 remove(),效率較低。get(int index):RangeCheck(index) 後直接 elementData[index],**隨機訪問 O(1)** 是 ArrayList 最大優勢;set(int index, E element):覆蓋指定位置,返回舊值。writeObject 只寫入 size 個有效元素,readObject 恢復時按實際大小分配數組;trimToSize():elementData = Arrays.copyOf(elementData, size),釋放多餘預留空間,適合「構建完成後不再變動」的場景。Collections.synchronizedList(new ArrayList<>())、CopyOnWriteArrayList(讀多寫少);new ArrayList<>(estimatedSize) 減少擴容拷貝;addAll 優於循環 add;LinkedList;new ArrayList<>(list) 避免 ConcurrentModificationException。ArrayList 以 動態數組 + 1.5倍擴容 + System.arraycopy 批量移動 為核心,提供了極快的隨機訪問與尾部添加,是「讀多寫少、順序訪問、可預估規模」場景的首選。掌握其擴容邏輯、移動數組的 O(n) 代價、transient 序列化設計,能讓你在容量規劃、性能調優、避坑併發修改上做出最優決策。