List 作為有序集合的核心接口,其四大實現類 ArrayList、LinkedList、Vector、Stack 在底層結構、性能特徵、線程安全性上差異顯著。本文通過源碼級原理分析與百萬級基準測試,給出清晰的選型決策依據。
Collection
↑
List (Interface)
↑
AbstractList (Abstract Class)
↑ ↑
ArrayList Vector
↑
Stack
↑
AbstractSequentialList
↑
LinkedList
O(1),插刪 O(n),非線程安全。O(n),首尾插刪 O(1),實現 Deque,非線程安全。synchronized,線程安全但性能較差。push/pop/peek 委託數組末尾操作。| 操作 | ArrayList | LinkedList | Vector | Stack |
|---|---|---|---|---|
| 頭部插入 10 萬 | 1617 ms | 29 ms | 1607 ms | 1640 ms |
| 頭部刪除 10 萬 | 1909 ms | 15 ms | 1910 ms | 1916 ms |
| 隨機讀取 10 萬 | 5 ms | 10809 ms | 6 ms | 9 ms |
結論:
- 頻繁頭部/中間插刪 → LinkedList 碾壓級優勢。
- 高頻隨機訪問/尾部追加 → ArrayList 極致性能。
- Vector/Stack 因同步開銷,單線程下性能與 ArrayList 持平但無優勢;多線程下建議改用
Collections.synchronizedList或CopyOnWriteArrayList。
// ArrayList.add(index, e) 核心
System.arraycopy(elementData, index, elementData, index + 1, size - index);
// 必須將 index 之後所有元素向後挪一位 → O(n)
// LinkedList.add(index, e) 核心
Entry<E> newEntry = new Entry<>(e, successor, predecessor);
predecessor.next = newEntry;
successor.previous = newEntry;
// 僅修改前後節點指針 → O(1) 定位後(定位本身 O(n/2))
// ArrayList.get(index)
return (E) elementData[index]; // 直接下標 → O(1)
// LinkedList.get(index)
Entry<E> e = header;
if (index < (size >> 1)) { for (i=0; i<=index; i++) e = e.next; }
else { for (i=size; i>index; i--) e = e.previous; }
return e.element; // 需遍歷鏈表 → O(n)
LinkedList 優化:索引 < size/2 從頭向後,否則從尾向前,但仍屬線性級。
| 類 | 默認容量 | 擴容公式 |
|---|---|---|
| ArrayList | 10 | newCapacity = (oldCapacity * 3) / 2 + 1(1.5 倍 + 1) |
| Vector | 10 | capacityIncrement > 0 ? old + increment : old * 2(可配置增量) |
| 維度 | ArrayList | Vector |
|---|---|---|
| 線程安全 | 否 | 是(方法級 synchronized) |
| 序列化 | 實現 Serializable | 未實現 Serializable |
| 構造函數 | 3 個 | 4 個(額外 capacityIncrement) |
| 遍歷支持 | Iterator、ListIterator、for-each | 額外支持 Enumeration |
| 擴容倍數 | 固定 1.5 倍 | 可配置或 2 倍 |
iteratorThroughRandomAccess:6 ms // 下標訪問最快
iteratorThroughEnumeration:7 ms
iteratorThroughFor2:8 ms
iteratorThroughIterator:9 ms // 迭代器最慢
建議:Vector 優先使用下標隨機訪問遍歷。
ArrayDeque(非線程安全)或 LinkedList(實現 Deque),勿用 Stack/Vector。initialCapacity 減少擴容。for (E e : list) 或 list.forEach()。Iterator.remove(),避免 ConcurrentModificationException。java.util.concurrent 包下並發集合。LinkedList 中使用 get(index)/set(index) 進行批量隨機訪問。