核心類:ArrayList
- 動態陣列實現
List 介面
- 非執行緒安全,多執行緒環境需同步或用
CopyOnWriteArrayList
- 隨機存取 O(1),尾部增刪 O(1),中間增刪 O(n)
基本操作範例
package com.example.list;
import java.util.ArrayList;
import java.util.List;
class Student {
private String name;
private int id;
private String color;
public Student(String name, int id, String color) {
this.name = name;
this.id = id;
this.color = color;
}
// getter 省略
public String getName() { return name; }
public int getId() { return id; }
public String getColor() { return color; }
}
public class ArrayListDemo {
public static void main(String[] args) {
List list = new ArrayList<>();
// 新增
list.add(new Student("小紅", 13, "紅色"));
list.add(new Student("小明", 12, "黃色"));
list.add(new Student("小強", 123, "藍色"));
// 指定位置插入
list.add(1, new Student("小北", 2, "brave")); // 索引 1 處插入
// 刪除:按索引
list.remove(0); // 刪除第一個
// 刪除:按物件(需正確實現 equals)
Student toRemove = new Student("小李", 23, "白色");
list.add(toRemove);
list.remove(toRemove); // 依賴 equals 比較
// 遍歷方式對比
System.out.println("=== for 迴圈 ===");
for (int i = 0; i < list.size(); i++) {
Student s = list.get(i);
System.out.printf("%d: %s, %d, %s%n", i+1, s.getName(), s.getId(), s.getColor());
}
System.out.println("=== 增強 for ===");
for (Student s : list) {
System.out.println(s.getName());
}
System.out.println("=== Iterator(安全刪除) ===");
Iterator it = list.iterator();
while (it.hasNext()) {
Student s = it.next();
if (s.getId() > 100) {
it.remove(); // 唯一安全的遍歷中刪除方式
}
}
System.out.println("=== Java 8 forEach ===");
list.forEach(s -> System.out.println(s.getName()));
System.out.println("=== Stream 過濾 ===");
list.stream()
.filter(s -> s.getId() < 50)
.forEach(s -> System.out.println(s.getName() + " (ID<50)"));
}
}
關鍵陷阱:遍歷中刪除
❌ 錯誤做法
// ConcurrentModificationException 必現
for (Student s : list) {
if (s.getId() > 100) {
list.remove(s); // 直接修改結構,破壞迭代器預期
}
}
// 索引迴圈刪除也會漏刪
for (int i = 0; i < list.size(); i++) {
if (list.get(i).getId() > 100) {
list.remove(i); // 刪除後後續元素前移,i++ 導致跳過下一個
}
}
✅ 正確做法
| 場景 | 正確寫法 |
| 單執行緒,需邊遍歷邊刪 | 使用 Iterator.remove() |
| 單執行緒,先篩選後批量刪 | list.removeIf(s -> s.getId() > 100) (Java 8+) |
| 單執行緒,創建新列表 | list = list.stream().filter(...).collect(toList()) |
| 多執行緒環境 | 用 CopyOnWriteArrayList 或加鎖 |
效能特徵與選型
| 操作 | ArrayList | LinkedList | CopyOnWriteArrayList |
| 隨機存取 get(i) | O(1) ⭐ | O(n) | O(1) |
| 尾部新增 add(e) | O(1) 擴容均攤 | O(1) | O(n) 複製陣列 |
| 中間插入/刪除 | O(n) 移動元素 | O(1) 找到位置後 | O(n) 複製陣列 |
| 遍歷 | 極快(緩存友好) | 較慢 | 快 |
| 併發讀多寫少 | 需外部同步 | 需外部同步 | 無鎖讀取 ⭐ |
最佳實踐總結
- 預設選 ArrayList:90% 場景下最優
- 指定初始容量:`new ArrayList<>(expectedSize)` 減少擴容複製
- 遍歷刪除用 removeIf/Iterator:避免 CME 異常
- 併發場景:讀多寫少 →
CopyOnWriteArrayList;寫多 → Collections.synchronizedList 或並發隊列
- 不可變視圖:`List.of()` (Java 9+)、`Collections.unmodifiableList()`
總結
ArrayList 是 Java 開發最高頻的集合類。掌握其擴容機制、遍歷刪除正確姿勢、併發限制,能避開 80% 的生產故障。記住:有疑問時選 ArrayList,有併發時想清楚再選。