| 方法 | 說明 | 時間複雜度 (ArrayList) |
add(E e) | 尾部添加 | O(1) 均攤 |
add(int index, E e) | 指定位置插入 | O(n) |
get(int index) | 獲取元素 | O(1) |
set(int index, E e) | 替換元素 | O(1) |
remove(int index) | 刪除指定位置 | O(n) |
remove(Object o) | 刪除首個匹配元素 | O(n) |
indexOf(Object o) | 首次出現索引 | O(n) |
contains(Object o) | 是否包含 | O(n) |
size() | 元素數量 | O(1) |
isEmpty() | 是否為空 | O(1) |
clear() | 清空 | O(1) |
subList(from, to) | 視圖切片 [from, to) | O(1) (視圖) |
toArray() | 轉數組 | O(n) |
迭代器模式:統一遍歷抽象
所有 Collection 實現 Iterable,提供 iterator() 返回 Iterator:
List<String> list = new ArrayList<>();
list.add("A"); list.add("B"); list.add("C");
// 1. Iterator 顯式遍歷 (通用、可刪除)
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String s = it.next();
System.out.println(s);
if ("B".equals(s)) it.remove(); // 安全刪除
}
// 2. 增強 for (語法糖,內部用 Iterator,不可刪除)
for (String s : list) System.out.println(s);
// 3. forEach + Lambda (Java 8+)
list.forEach(System.out::println);
// 4. Stream 流式處理
list.stream().filter(s -> s.length() > 1).forEach(System.out::println);
// 5. ListIterator (雙向、可修改、可獲取索引) - 僅 List 有
ListIterator<String> lit = list.listIterator();
while (lit.hasNext()) {
int idx = lit.nextIndex();
String s = lit.next();
lit.set(s + idx); // 修改
}
lit.previous(); // 逆向
實戰示例:學生管理系統
import java.util.*;
class Student {
String name; int age;
Student(String name, int age) { this.name = name; this.age = age; }
@Override public String toString() { return name + "(" + age + ")"; }
}
public class ListDemo {
public static void main(String[] args) {
List<Student> students = new ArrayList<>();
// 添加
students.add(new Student("Alice", 20));
students.add(new Student("Bob", 22));
students.add(1, new Student("Charlie", 19)); // 插入索引 1
// 遍歷輸出
System.out.println("所有學生: " + students);
// 索引訪問
System.out.println("第一個: " + students.get(0));
// 修改
students.set(1, new Student("Bob-Updated", 23));
// 查找
int idx = students.indexOf(new Student("Bob-Updated", 23)); // 需重寫 equals
System.out.println("Bob 索引: " + idx);
// 刪除
students.remove(0); // 刪除索引 0
students.remove(new Student("Charlie", 19)); // 刪除對象 (需 equals)
// 批量操作
List<Student> more = Arrays.asList(new Student("David", 21), new Student("Eve", 20));
students.addAll(more);
students.retainAll(Arrays.asList(new Student("Bob-Updated", 23))); // 只保留交集
// 轉數組
Student[] arr = students.toArray(new Student[0]);
// 排序 (需 Comparable 或 Comparator)
students.sort(Comparator.comparingInt(s -> s.age));
System.out.println("按年齡排序: " + students);
}
}
常見陷阱與避坑
| 陷阱 | 代碼 | 後果 | 解決 |
| for 循環中 remove 導致索引錯亂 | for (int i=0; i| 漏刪/越界 | 倒序遍歷 / Iterator.remove() / removeIf() | |
| 增強 for 中 remove | for (String s : list) if(...) list.remove(s); | ConcurrentModificationException | 用 Iterator 或 removeIf |
| subList 視圖修改影響原列表 | List<String> sub = list.subList(0,2); sub.clear(); | 原列表前兩個被刪 | 明確語義,或 new ArrayList<>(subList) 復制 |
| asList 返回固定長度列表 | List<String> list = Arrays.asList("a","b"); list.add("c"); | UnsupportedOperationException | new ArrayList<>(Arrays.asList(...)) |
| 基本類型無法泛型化 | List<int> list = new ArrayList<>(); | 編譯錯誤 | 用包裝類 List<Integer> |
性能優化建議
- 預估大小預分配:
new ArrayList<>(expectedSize) 避免多次擴容複製
- 批量添加用 addAll:比循環 add 高效
- 頻繁中間增刪:考慮
LinkedList 或數據結構重設計
- 並發環境:
CopyOnWriteArrayList (讀多寫少) 或 Collections.synchronizedList (均衡)
- 只讀列表:
Collections.unmodifiableList(list) 或 List.of(...) (Java 9+)
總結
List 是 Java 業務開發最高頻集合。掌握 ArrayList 為主、LinkedList 為輔 的選型邏輯,熟練使用 Iterator 安全遍歷刪除、removeIf 批量刪除、subList 視圖語義、預分配優化,警惕 並發修改異常、基本類型泛型化、asList 固定長度 三大坑,即可寫出高性能、無 Bug 的列表操作代碼。
- 上一篇文章: MyBatis 啟動無限打印「Logging initialized」日誌:根因定位與徹底解決
- 下一篇文章: Java 多線程:線程啟動、中斷、終止完整指南 (start vs run, interrupt, 安全停止模式)
Copyright ©
程式碼之家 All Rights Reserved