keySet()、values()、entrySet()| 實作類 | 有序性 | 同步 | Null Key/Value | 適用場景 |
|---|---|---|---|---|
| HashMap | 無序 | 否 | 允許 | 通用高效存取 |
| LinkedHashMap | 插入序/訪問序 | 否 | 允許 | LRU 快取、需保持順序 |
| TreeMap | 自然序/比較器序 | 否 | 不允許 null Key | 範圍查詢、有序遍歷 |
| Hashtable | 無序 | 是 | 禁止 | 舊代碼相容(建議用 ConcurrentHashMap) |
| ConcurrentHashMap | 無序 | 是(分段鎖/CAS) | 禁止 | 高併發讀寫 |
| WeakHashMap | 無序 | 否 | 允許 | 快取、監聽器註冊(Key 可被 GC 回收) |
| IdentityHashMap | 無序 | 否 | 允許 | Key 用 == 比較而非 equals() |
Map<String, Integer> scores = new HashMap<>();
// 增/改
scores.put("Alice", 95);
scores.put("Bob", 88);
scores.putIfAbsent("Alice", 100); // 不覆蓋既有值
// 刪
Integer removed = scores.remove("Bob");
scores.remove("Charlie", 60); // 僅當值匹配才移除
// 查
Integer alice = scores.get("Alice");
boolean hasBob = scores.containsKey("Bob");
boolean has95 = scores.containsValue(95);
// 遍歷(推薦 entrySet)
for (Map.Entry<String, Integer> entry : scores.entrySet()) {
System.out.println(entry.getKey() + " = " + entry.getValue());
}
// Java 8+ 函數式遍歷
scores.forEach((k, v) -> System.out.println(k + " -> " + v));
// 合併/計算
scores.merge("Alice", 5, Integer::sum); // 95 + 5 = 100
scores.computeIfAbsent("David", k -> 0); // 不存在則放入 0
重寫 equals() 必須重寫 hashCode(),且兩者必須一致
public class Student {
private String id;
private String name;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Student)) return false;
Student that = (Student) o;
return Objects.equals(id, that.id); // 僅用 id 判斷相等
}
@Override
public int hashCode() {
return Objects.hash(id); // 僅用 id 計算 hash
}
}
違反規則後果:map.get(key) 回傳 null、無法移除、記憶體洩漏。
// 方案一:List 作為 Value
Map<String, List<String>> groups = new HashMap<>();
groups.computeIfAbsent("Java", k -> new ArrayList<>()).add("Alice");
// 方案二:Guava Multimap / Apache ListValuedMap
// 方案三:Java 9+ Map.merge
groups.merge("Java", new ArrayList<>(List.of("Bob")), (old, nw) -> { old.addAll(nw); return old; });
Map<String, Long> freq = new HashMap<>();
words.forEach(w -> freq.merge(w, 1L, Long::sum));
Map<String, List<User>> byCity = users.stream()
.collect(Collectors.groupingBy(User::getCity));
| 坑點 | 後果 | 修正 |
|---|---|---|
| 遍歷時修改 Map | ConcurrentModificationException | 用 Iterator.remove() 或收集待刪 Key 後再刪 |
| 可變物件作 Key | 修改後無法查找 | Key 必須不可變(String、Integer、自定義 immutable 類) |
| HashMap 多執行緒 put | 死循環/資料遺失 | 改用 ConcurrentHashMap 或 Collections.synchronizedMap |
| TreeMap Key 未實作 Comparable | ClassCastException | Key 實作 Comparable 或提供 Comparator |