JDK 5.0 Collection 最大變革:泛型化。本文實戰總結核心新特性與最佳實踐。
// 舊寫法
for (Iterator it = c.iterator(); it.hasNext(); ) {
String s = (String) it.next();
}
// 新寫法:適用所有實作 Iterable 介面的類型
for (String s : c) { ... }
注意:需存取索引或 Iterator 本身 (如刪除、判斷首項) 時仍需傳統寫法。
// Collections.singletonList(T o) → 推論 T
List list = Collections.singletonList("hello"); // T=String
// 無參泛型方法:從賦值目標推論
List empty = Collections.emptyList(); // T=Integer
// 條件運算子中無法推論 → 顯式指定
List list = flag ? Collections.emptyList() : null;
| 類型 | 特性 | 適用場景 |
|---|---|---|
| ArrayList | 動態陣列、隨機存取 O(1)、中間刪除 O(n)、非執行緒安全 | 單執行緒、頻繁隨機存取 |
| LinkedList | 雙向鏈表、首尾增刪 O(1)、循序存取、get(n) 實為 O(n) | 佇列/棧、頻繁首尾操作 |
| HashSet | Hash 索引、拒重複、無序 | 快速存在性檢查 |
| TreeSet | 紅黑樹、有序、O(log n) | 需排序的無重複集合 |
| LinkedHashSet | 維持插入順序 | 需插入順序的去重 |
| PriorityQueue | 最小元素優先出佇列 | 任務調度、演算法 |
| HashMap | Key-Value、非執行緒安全、效能優於 Hashtable | 一般對映需求 |
| TreeMap | Key 有序 | 需排序對映 |
| LinkedHashMap | 維持插入/存取順序 | LRU 快取實作 |
// 讀取:用上限
void readList(List extends Number> list) { Number n = list.get(0); }
// 寫入:用下限
void writeList(List super Integer> list) { list.add(5); }
// API 設計:盡量用通配符擴大適用範圍
void removeNegatives(List extends Number> list); // 接受 List, List...
泛型擦除導致無法 `new T[]`。解法:建構式傳入 `Class
public class ArrayExample {
private final Class clazz;
public ArrayExample(Class clazz) { this.clazz = clazz; }
@SuppressWarnings("unchecked")
public T[] getArray(int size) {
return (T[]) Array.newInstance(clazz, size);
}
}
// 使用:new ArrayExample(String.class).getArray(10)
子類覆寫方法可回傳更具體類型,避免強制轉型、暴露欄位、專用方法三種反模式。