| 實作類 | 底層結構 | 隨機存取 | 插入/刪除 | 線程安全 | 適用場景 |
|---|---|---|---|---|---|
| ArrayList | 動態陣列 | O(1) 快 | O(n) 慢 (需位移) | 否 | 頻繁讀取、少量修改 |
| LinkedList | 雙向鏈表 | O(n) 慢 | O(1) 快 (僅改指標) | 否 | 頻繁頭尾增刪、佇列/棧 |
| Vector | 動態陣列 | O(1) | O(n) | 是 (同步) | 多線程舊代碼 |
| Stack | 繼承 Vector | O(1) | O(n) | 是 | LIFO 棧 (建議用 ArrayDeque) |
需要快速隨機存取 (get/indexOf)? → ArrayList
需要頻繁頭尾增刪、實作 Queue/Deque? → LinkedList (或 ArrayDeque)
多線程共享列表? → Collections.synchronizedList / CopyOnWriteArrayList
單線程、高效能棧/佇列? → ArrayDeque (最佳選擇)
| 操作 | ArrayList | LinkedList | Vector | Stack |
|---|---|---|---|---|
| 頭部插入 10 萬次 | 1,617 ms | 29 ms | 1,607 ms | 1,640 ms |
| 頭部刪除 10 萬次 | 1,909 ms | 15 ms | 1,910 ms | 1,916 ms |
| 索引遍歷 10 萬次 | 5 ms | 10,809 ms | 6 ms | 9 ms |
結論:LinkedList 頭尾增刪碾壓陣列類;隨機存取陣列類完勝。Vector/Stack 同步開銷大,單線程勿用。
public void add(int index, E element) {
ensureCapacity(size + 1);
// 核心開銷:JNI 級記憶體複製,移動 index 後所有元素
System.arraycopy(elementData, index, elementData, index + 1, size - index);
elementData[index] = element;
size++;
}
System.arraycopy 是 Native 方法,雖快但隨資料量線性增長。
public void add(int index, E element) {
addBefore(element, (index == size ? header : node(index)));
}
private Node<E> node(int index) {
// 雙向優化:index < size/2 從頭找,否則從尾找
if (index < (size >> 1)) {
for (Node<E> x = first; x != null; x = x.next) ...
} else {
for (Node<E> x = last; x != null; x = x.prev) ...
}
}
private void linkBefore(E e, Node<E> succ) {
Node<E> pred = succ.prev;
Node<E> newNode = new Node<>(pred, e, succ);
succ.prev = newNode;
if (pred == null) first = newNode;
else pred.next = newNode;
size++; modCount++;
}
僅修改前後節點指標,無記憶體大量複製。
elementData[index] 直接記憶體偏移,CPU 緩存友好synchronized,ArrayList 無(old*3)/2+1;Vector 可指定增量,預設 2 倍Vector(capacity, increment)elements() 回傳 Enumeration,ArrayList 無Serializable,Vector 早期版本未實作// 一般列表
List<String> list = new ArrayList<>();
// 高併發讀多寫少
List<String> safeList = new CopyOnWriteArrayList<>();
// 佇列/棧 (單線程)
Deque<String> queue = new ArrayDeque<>();
queue.addLast("a"); queue.pollFirst();
// 佇列/棧 (多線程)
BlockingQueue<String> mq = new LinkedBlockingQueue<>();
口訣:查多改少 ArrayList,改多查少 LinkedList,但實測才是真理——ArrayDeque 通常比 LinkedList 更快且記憶體更省。