List<E> 是 Java 集合框架中最常用的有序、可重複元素容器。本文系統對比 ArrayList、LinkedList、Vector 核心差異,解析 5 種遍歷方式性能,實戰隊列棧模擬,建立完整選型決策模型。
| 特性 | ArrayList | LinkedList | Vector (legacy) |
|---|---|---|---|
| 底層結構 | 動態數組 Object[] | 雙向鏈表 | 動態數組 |
| 隨機訪問 get(i) | O(1) ⚡ | O(n) 🐢 | O(1) |
| 頭/尾插入刪除 | O(n) / O(1)* | O(1) ⚡ | O(n) / O(1)* |
| 中間插入刪除 | O(n) | O(1) 定位後 | O(n) |
| 內存開銷 | 低 (連續) | 高 (節點對象) | 低 |
| 線程安全 | ❌ | ❌ | ✅ (同步方法) |
| 擴容機制 | 1.5倍 | 無 | 2倍 |
| 實現接口 | List, RandomAccess, Cloneable, Serializable | List, Deque, Cloneable, Serializable | List, RandomAccess... |
* 尾部插入攤銷 O(1),擴容時 O(n)
| 方式 | 代碼模式 | ArrayList | LinkedList | 推薦指數 |
|---|---|---|---|---|
| 1. 傳統 for 索引 | for(int i=0;i<size;i++) list.get(i) | ⚡ 最快 | 🐢 極慢 (O(n²)) | ArrayList ✅ |
| 2. 增強 for (for-each) | for(E e : list) | ⚡ 快 (隱式迭代器) | ⚡ 快 (隱式迭代器) | 通用 ✅✅✅ |
| 3. 顯式 Iterator | Iterator<E> it=list.iterator() | ⚡ 快 | ⚡ 快 | 需刪除時 ✅ |
| 4. ListIterator | ListIterator<E> it=list.listIterator() | ⚡ 快 (雙向) | ⚡ 快 (雙向) | 需反向/修改 ✅ |
| 5. Stream API | list.stream().forEach() | 快 (略慢於 for-each) | 快 | 函數式鏈式 ✅ |
| 6. 並行流 | list.parallelStream().forEach() | 多核加速 (大數據) | ❌ 不推薦 (分割困難) | CPU 密集 ✅ |
List list = new ArrayList<>(List.of("A", "B", "C"));
// 1. 增強 for (最通用、最推薦)
for (String s : list) { System.out.println(s); }
// 2. Iterator (需邊遍歷邊刪除)
Iterator it = list.iterator();
while (it.hasNext()) {
String s = it.next();
if ("B".equals(s)) it.remove(); // 安全刪除
}
// 3. ListIterator (反向遍歷、指定位置插入)
ListIterator lit = list.listIterator(list.size());
while (lit.hasPrevious()) {
System.out.println(lit.previous()); // 反向輸出
}
// 4. Stream (函數式鏈式操作)
list.stream()
.filter(s -> s.compareTo("B") > 0)
.map(String::toLowerCase)
.forEach(System.out::println);
// 5. 傳統 for (ArrayList 專用高性能)
for (int i = 0, n = list.size(); i < n; i++) {
String s = list.get(i); // O(1)
}
LinkedList 實現 Deque 接口,原生支援隊列 (FIFO) 和棧 (LIFO):
// 隊列 (FIFO: 先進先出)
Deque queue = new LinkedList<>();
queue.addLast("task1"); // 入隊
queue.addLast("task2");
String head = queue.removeFirst(); // 出隊 -> "task1"
String peek = queue.peekFirst(); // 查看隊首不移除
// 棧 (LIFO: 後進先出)
Deque stack = new LinkedList<>();
stack.addFirst("frame1"); // 入棧
stack.addFirst("frame2");
String top = stack.removeFirst(); // 出棧 -> "frame2"
String peekTop = stack.peekFirst(); // 查看棧頂
// 封裝工具類
public class DequeUtils {
public static Queue newQueue() { return new LinkedList<>(); }
public static Deque newStack() { return new LinkedList<>(); }
// 隊列操作
public static void enqueue(Queue q, E e) { ((Deque)q).addLast(e); }
public static E dequeue(Queue q) { return ((Deque)q).removeFirst(); }
// 棧操作
public static void push(Deque s, E e) { s.addFirst(e); }
public static E pop(Deque s) { return s.removeFirst(); }
}
| 方案 | 適用場景 | 性能 | 代碼示例 |
|---|---|---|---|
Collections.synchronizedList | 低併發、簡單同步 | 中等 (全鎖) | List<T> list = Collections.synchronizedList(new ArrayList<>()); |
CopyOnWriteArrayList | 讀多寫少、遍歷不阻塞 | 寫入慢 (複製數組) | List<T> list = new CopyOnWriteArrayList<>(); |
| 手動同步 | 複雜邏輯、批量操作 | 可控 | synchronized(list) { ... } |
| 並發佇列 | 生產者消費者 | 高 (無鎖/CAS) | Queue<T> q = new ConcurrentLinkedQueue<>(); |
需要 List
│
├─ 高頻隨機訪問 get(i)、末尾增刪、內存敏感 → ArrayList (默認首選)
├─ 高頻頭部/中間增刪、需隊列/棧語義 → LinkedList
├─ 多線程讀多寫少、遍歷不阻塞 → CopyOnWriteArrayList
├─ 多線程寫多、需復合操作原子性 → Collections.synchronizedList + 手動鎖
├─ 異步生產消費 → ConcurrentLinkedQueue / LinkedBlockingQueue
└─ 歷史代碼維護 → Vector (新代碼禁用)
new ArrayList<>(Arrays.asList(...))equals() 和 hashCode()Iterator.remove()List<Integer> 存儲基本類型有對象開銷,大數據考慮 IntList (Eclipse Collections/FastUtil)// 只有元素,不可修改 (結構+內容)
List immutable = List.of("A", "B", "C"); // Java 9
List immutable2 = List.copyOf(mutableList); // Java 10
// 特性:Null 不允許、結構不可變、元素不可變 (若元素本身不可變)、
// 實現類為內部類、序列化支援、極致內存緊湊