對於許多 Java 開發者而言,ArrayList 和 HashMap 幾乎是 Java Collections API 的代名詞。然而,這僅僅是冰山一角。Java 集合框架不僅是取代陣列的優秀替代品,更蘊含著豐富的進階特性,能夠優化代碼結構、提升效能並解決棘手的併發問題。本文將深入探討五個關鍵技巧,助你從「會用」進階到「善用」。
早期 Java 引入陣列主要是為了回應 C++ 開發者對效能的質疑,但現代 JVM 對集合類的優化已使其效能不遜於陣列。集合提供了豐富的現成方法,例如所有 Collection 實現都內建的 toString(),讓輸出除錯資訊變得極為簡單。
最佳實踐: 遇到陣列應盡快轉為集合。使用 Arrays.asList() 可一鍵完成轉換:
String[] args = {"a", "b", "c"};
List<String> list = Arrays.asList(args); // 返回固定大小的 List
System.out.println(list); // 直接輸出 [a, b, c]
注意: 此方法返回的 List 結構不可變(無法增刪元素),若需可修改列表,請用 new ArrayList<>(Arrays.asList(args)) 包裝。
在集合間搬移資料或批量移除元素時,切勿手寫 for 迴圈逐一 add/remove。這不僅因頻繁擴容導致效能低落,更在多線程環境下引發鎖競爭與 Race Condition。
正確姿勢: 使用 addAll(Collection) 與 removeAll(Collection) 進行批量操作,這些方法內部優化了擴容邏輯,且在同步集合中屬於原子操作,能有效規避併發風險。
Java 5 引入的增強型 for 循環(for (E e : iterable))消除了手動操作 Iterator 的樣板代碼。關鍵在於:任何實作 Iterable 介面的物件皆可使用,不限於 Collection。
這為領域建模帶來新可能。例如 Person 類別實作 Iterable<Person>,內部封裝 children 列表,對外僅暴露遍歷能力,防止外部隨意修改孩子列表:
public class Person implements Iterable<Person> {
private List<Person> children = new ArrayList<>();
// ... 建構子與 getter ...
@Override
public Iterator<Person> iterator() {
return children.iterator(); // 委派給內部列表
}
}
// 使用時極其自然
for (Person kid : ted) { System.out.println(kid.getName()); }
Collections 工具類提供了大量靜態演算法方法(如 reverse、sort、shuffle),它們針對介面而非具體實現編程,體現了「依賴倒置」原則。
範例: 反轉列表順序
List<Person> kids = new ArrayList<>(person.getChildren());
Collections.reverse(kids); // 原地反轉
若不想修改原列表,可自寫不變式演算法:
public static <T> List<T> reversed(List<T> src) {
List<T> copy = new ArrayList<>(src);
Collections.reverse(copy);
return copy;
}
Java 集合框架設計之初即預留了擴展點。當標準集合無法滿足業務需求(如「自動按年齡排序的子女列表」)時,可通過組合現有類快速構建自訂集合。
核心步驟:
Collection<E>,宣告領域專屬行為(如 getComparator())。ArrayList,在所有修改方法(add、remove 等)後呼叫 Collections.sort()。Iterable 以支援 for-each 遍歷。這樣既復用了成熟的底層邏輯,又封裝了業務規則,讓客戶端代碼保持乾淨。
Java Collections API 的設計哲學是「開放擴展,封閉修改」。掌握這五大技巧——轉換陣列、批量操作、泛化遍歷、善用演算法、自訂集合——將讓你在日常開發中游刃有餘。下一篇將繼續揭秘更多進階用法。