首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java Map 介面完整解析與實戰應用

     編輯:Java 相關知識

Map 核心特性

  • 鍵值對映射:Key → Value,Key 唯一,Value 可重複
  • 非同步:HashMap 非執行緒安全,Hashtable 同步
  • 允許 null:HashMap 允許 null Key/Value,Hashtable 禁止
  • 三種視圖: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

Key 設計關鍵規則

重寫 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、無法移除、記憶體洩漏。

進階應用模式

1. 多值映射

// 方案一: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; });

2. 計數器

Map<String, Long> freq = new HashMap<>();
words.forEach(w -> freq.merge(w, 1L, Long::sum));

3. 分組收集

Map<String, List<User>> byCity = users.stream()
    .collect(Collectors.groupingBy(User::getCity));

效能調優建議

  1. 預估容量:`new HashMap<>(expectedSize / 0.75f + 1)` 避免擴容
  2. 避免自動裝箱:大量基本型別用 Trove/Guava 原生集合或陣列
  3. 高併發選 ConcurrentHashMap:JDK 8+ 採用 CAS + synchronized + 紅黑樹,擴容無鎖
  4. 遍歷選 entrySet:單次查找同時取得 Key/Value,避免重複 `get()`

常見坑點

坑點後果修正
遍歷時修改 MapConcurrentModificationException用 Iterator.remove() 或收集待刪 Key 後再刪
可變物件作 Key修改後無法查找Key 必須不可變(String、Integer、自定義 immutable 類)
HashMap 多執行緒 put死循環/資料遺失改用 ConcurrentHashMap 或 Collections.synchronizedMap
TreeMap Key 未實作 ComparableClassCastExceptionKey 實作 Comparable 或提供 Comparator
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved