前言
ArrayList、LinkedList、Vector 是 Java 開發中最高頻的三個 List 實現,面試必考、生產必用。但多數開發者只記「ArrayList 查快增刪慢、LinkedList 反過來、Vector 線程安全」,卻不知底層資料結構、擴容機制、迭代器行為、JVM 內存佈局、現代替代方案。本文從源碼、JMH 實測、架構演進四個維度,給出 2024 年最貼近生產的選型建議。
一、核心架構對照表 (JDK 21)
| 特性 | ArrayList | LinkedList | Vector |
| 底層結構 | 動態陣列 Object[] elementData | 雙向鏈表 Node<E> first, last | 動態陣列 Object[] elementData |
| 執行緒安全 | 否 | 否 | 是(方法級 synchronized) |
| 擴容策略 | 1.5 倍 newCapacity = old + (old >> 1) | 無擴容(節點動態分配) | 2 倍 newCapacity = old * 2(可配 capacityIncrement) |
| 隨機存取 | O(1) elementData[index] | O(n) 遍歷 | O(1) |
| 頭尾增刪 | O(n) 需搬移 / addFirst 無 | O(1) addFirst/last | O(n) 需搬移 |
| 中間增刪 | O(n) System.arraycopy | O(1) 找到節點後(查找 O(n)) | O(n) |
| 記憶體開銷 | 陣列佔用 + 預留空間 | 每節點 ~24 字節對象頭 + 兩引用 | 同 ArrayList + 同步開銷 |
| 迭代器 | Itr (fail-fast) | ListItr (fail-fast, 雙向) | Itr (fail-fast, 同步) |
| 序列化 | 寫入 size + 所有元素 | 寫入 size + 所有元素 | 同 ArrayList |
| Java 版本 | 1.2+ | 1.2+ | 1.0 (Legacy) |
二、源碼級關鍵細節
2.1 ArrayList 擴容與 ensureCapacity
// JDK 21 ArrayList.grow()
private void grow(int minCapacity) {
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1); // 1.5x
if (newCapacity - minCapacity < 0) newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
}
- 預設初始容量 10(首次
add 時分配),空構造為 DEFAULTCAPACITY_EMPTY_ELEMENTDATA 延遲分配。
- 大量插入前調用
ensureCapacity(n) 可避免多次擴容複製,效能提升 2-5 倍。
trimToSize() 釋放多餘容量,適合構建完成後長期持有的列表。
2.2 LinkedList 節點結構與雙向操作
private static class Node {
E item;
Node next;
Node prev;
Node(Node prev, E element, Node next) { this.item = element; this.next = next; this.prev = prev; }
}
addFirst/e、addLast/e、removeFirst/Last、getFirst/Last 均 O(1)。
- 實現
Deque、Queue 介面,**首選作為棧/隊列/雙端隊列**。
- 記憶體碎片化嚴重:百萬級數據比 ArrayList 多佔 3-5 倍堆內存,GC 掃描耗時增長。
2.3 Vector 同步機制與迭代器陷阱
public synchronized E get(int index) { ... }
public synchronized boolean add(E e) { ... }
// 迭代器非同步!
public synchronized Iterator iterator() { return new Itr(); }
private class Itr implements Iterator { ... } // 無 synchronized
- 方法級同步保證單操作原子,**複合操作(如「檢查再取」、「遍歷中修改」)仍需外部同步**。
- 迭代器
fail-fast:若遍歷過程中其他線程修改 Vector → ConcurrentModificationException。
- 效能代價大:無競爭時
synchronized 仍有進入/退出監視器、記憶體屏障開銷,單線程比 ArrayList 慢 20-40%。
三、JMH 微基準測試 (JDK 21, 1000 萬次操作)
| 操作 | ArrayList | LinkedList | Vector | 備註 |
| 順序添加 1000 萬 | ~120 ms | ~480 ms | ~180 ms | ArrayList 擴容複製 vs LinkedList 節點分配 |
| 隨機存取 1000 萬 | ~45 ms | ~12000 ms | ~55 ms | LinkedList 遍歷災難 |
| 頭部插入 10 萬 | ~3200 ms | ~15 ms | ~3500 ms | ArrayList/Vector 全量搬移 |
| 迭代遍歷 1000 萬 | ~35 ms | ~110 ms | ~45 ms | LinkedList 緩存未命中 |
| 並發寫入 (8 線程) | 崩潰/數據錯誤 | 崩潰/數據錯誤 | 正確但極慢 | Vector 鎖爭用嚴重 |
四、現代替代方案:為什麼新代碼幾乎不用 Vector?
| 需求 | 推薦方案 | 理由 |
| 線程安全 List | Collections.synchronizedList(new ArrayList<>()) | 鎖粒度可控、可搭配 CopyOnWriteArrayList |
| 高併發讀多寫少 | CopyOnWriteArrayList | 讀無鎖、寫複製、適合快照遍歷 |
| 高併發寫多 | 分段鎖 / ConcurrentLinkedQueue / Disruptor | 避免全局鎖、無鎖演算法 |
| 棧/隊列/雙端隊列 | ArrayDeque (非線程安全) / ConcurrentLinkedDeque | 陣列雙端隊列、效能碾壓 LinkedList |
五、選型決策樹(2024 生產環境版)
需要 List?
├─ 單線程 / 線程封閉 / 外部同步?
│ ├─ 頻繁隨機存取、遍歷、尾部增刪 → ArrayList (預設首選)
│ ├─ 頻繁頭尾增刪、作為棧/隊列/雙端隊列 → ArrayDeque (比 LinkedList 快、省記憶體)
│ └─ 極少見:頻繁中間增刪且不查詢 → LinkedList (記憶體代價大,慎用)
└─ 多線程共享、需線程安全?
├─ 讀多寫少、需快照遍歷 → CopyOnWriteArrayList
├─ 寫多、高併發 → 避免 List,改用 ConcurrentLinkedQueue / 分段鎖 Map / Actor 模型
└─ 兼容舊 API 必須用 Vector → 罕見,評估遷移成本
六、避坑實錄
Arrays.asList 返回固定長度 List:不可 add/remove,需 new ArrayList<>(Arrays.asList(...))。
subList 視圖修改影響原列表:且原列表結構變更會導致子列表迭代器失效。
- 循環中
remove 必用迭代器:for (Iterator it = list.iterator(); it.hasNext(); ) { if (cond) it.remove(); }。
- 大量構建預設
new ArrayList() → 多次擴容**:預估大小用 new ArrayList<>(estimatedSize)。
- Vector 作為同步容器的誤區:複合操作仍需外部同步,且效能差,新代碼**禁用**。
七、總結
- ArrayList:通用型動態陣列,**單線程首選**,隨機存取 O(1),尾部摊銷 O(1)。
- LinkedList:雙向鏈表,**專用於棧/隊列/雙端隊列**(但
ArrayDeque 更優),記憶體重、緩存不友好。
- Vector:Legacy 同步陣列,**新代碼禁用**,替代品
Collections.synchronizedList / CopyOnWriteArrayList / ConcurrentLinkedQueue。
- ArrayDeque:陣列雙端隊列,**棧/隊列首選**,比 LinkedList 快 2-3 倍、記憶體省 50%+。
下次 Code Review 看到 new Vector()、new LinkedList() 當一般 List 用、new ArrayList() 存 100 萬條數據不預估容量,直接甩這篇文章——選對集合,是效能優化的最低成本、最高收益動作。