LinkedList 基於雙向循環鏈表實現,不僅可作為列表使用,還實現了 Deque 接口,可作為棧、隊列、雙端隊列使用。它不是線程安全的,僅適用於單線程環境。LinkedList 實現了 Serializable 和 Cloneable 接口,支持序列化與克隆。
private static class Entry {
E element;
Entry next;
Entry previous;
Entry(E element, Entry next, Entry previous) {
this.element = element;
this.next = next;
this.previous = previous;
}
}
每個節點包含元素值、前驅指針、後繼指針,構成雙向鏈表。
private transient Entry header = new Entry<>(null, null, null);
// 構造函數初始化
header.next = header.previous = header;
header 是不存儲數據的哨兵節點,next 指向首節點,previous 指向尾節點,形成循環結構,簡化邊界條件判斷。
private Entry entry(int index) {
if (index < 0 || index >= size) throw new IndexOutOfBoundsException();
Entry e = header;
if (index < (size >> 1)) { // 從頭向後遍歷
for (int i = 0; i <= index; i++) e = e.next;
} else { // 從尾向前遍歷
for (int i = size; i > index; i--) e = e.previous;
}
return e;
}
優化策略:比較 index 與 size/2,選擇較短路徑遍歷,平均查找步數減半。
public boolean add(E e) {
addBefore(e, header); // 添加到尾部(header.previous)
return true;
}
private Entry addBefore(E e, Entry entry) {
Entry newEntry = new Entry<>(e, entry, entry.previous);
entry.previous.next = newEntry;
entry.previous = newEntry;
size++;
modCount++;
return newEntry;
}
尾部添加 O(1),指定位置插入需先定位節點 O(n),再調整指針 O(1)。
public E remove(int index) {
Entry e = entry(index);
return remove(e);
}
private E remove(Entry e) {
E result = e.element;
e.previous.next = e.next;
e.next.previous = e.previous;
e.next = e.previous = null;
e.element = null;
size--;
modCount++;
return result;
}
刪除同樣需先定位 O(n),調整指針 O(1),並幫助 GC 回收節點。
public E get(int index) {
return entry(index).element;
}
隨機訪問 O(n),不實現 RandomAccess 接口。
| 操作 | 方法 | 對應鏈表操作 |
|---|---|---|
| 棧 push | push(E e) | addFirst(e) - 頭部插入 |
| 棧 pop | pop() | removeFirst() - 刪除頭部 |
| 棧 peek | peek() | getFirst() - 獲取頭部 |
| 隊列 offer | offer(E e) | addLast(e) - 尾部插入 |
| 隊列 poll | poll() | removeFirst() - 刪除頭部 |
| 隊列 peek | peek() | getFirst() - 獲取頭部 |
| 特性 | LinkedList | ArrayList |
|---|---|---|
| 底層結構 | 雙向鏈表 | 動態數組 |
| 隨機訪問 | O(n) | O(1) |
| 頭尾增刪 | O(1) | O(n) / 擴容 |
| 中間增刪 | O(n) 定位 + O(1) 操作 | O(n) 移動元素 |
| 內存佔用 | 較大(節點對象 + 指針) | 較小(連續數組) |
| 緩存友好 | 差(內存不連續) | 好(連續內存) |
| 線程安全 | 否 | 否 |
LinkedList 以雙向循環鏈表為基礎,通過哨兵節點簡化邊界處理,雙向指針支持高效頭尾操作,實現 Deque 提供豐富棧隊功能。但隨機訪問性能弱、內存開銷大、緩存不友好,現代架構中除特定隊列棧場景外,ArrayList 往往是更優選擇。