博客 / 詳情

返回

Java Map家族全面解析:從基礎到高階應用

Map家族

1、頂層接口:Map<K,V>

  • 實現:定義了 鍵值對的存儲 的抽象接口

    • 常用方法:put() get() remove() containsKey() entrySet() keySet() values()
  • 底層:只是規範,並不關心具體數據結構
  • 應用:統一API,讓不同實現類有相同的使用方式
  • 作用:抽象層,解耦調用方與實現類

2、HashMap

  • 底層:

    • jdk 1.7:數組+鏈表 jdk1.8+:數組+鏈表+紅黑樹(後鏈表長度 > 8 時轉為紅黑樹)
    • 哈希函數:對hashCode做擾動運算,減少衝突
    • 擴容:容量翻倍,重新hash
  • 應用:緩存、統計、配置存儲
  • 作用:O(1)平均查找、插入效率 無序查找,效率優先
  • 業務場景(最常用的):

    1. 緩存:存儲一些臨時數據,比如一個用户的ID和用户信息的映射
    Map<Integer, User> userCache = new HashMap();
    userCache.put(1001, new User("wjj"));
    1. 快速查找:比如統計單詞出現的次數
    Map<String, Integer> countMap = HashMap<>();
    // 統計 apple 出現的次數,出現就+1,否則放入1
    1. 配置存儲:存儲一些配置項,比如數據庫連接參數(key=配置名,value=值)

3、LinkedHashMap

  • 底層:繼承HashMap,多了一個 雙向鏈表,保證插入順序或訪問順序
  • 特點:有序(插入順序 或 LRU順序)
  • 業務場景:

    1. LRU緩存(最常見):可以設置accessOrder = true ,自動把最近訪問的放到最後,淘汰最久沒有訪問的 (accessOrder 按照訪問順序排列 false就是按照插入順序)
    LinkedHashMap<Integer, String> lruCache = new LinkedHashMap<>(16, 0.75f, true);
    // 第一個參數:初始容量 第二個:負載因子(當元素超過16*0.75=12時進行擴容)
    // 第三個參數:是否按照訪問順序排序
    1. 需要順序輸出的情況:比如保存菜單項,按用户定義的順序展示

4、TreeMap

  • 底層:紅黑樹(有序二叉查找樹)
  • 特點:按照 key 排序(自然排序 or Comparator)。查找 / 插入O(logN)
  • 業務場景:

    1. 排行榜:比如存儲用户分數,key = 分數,value = 用户,天然排序
    TreeMap<Integer, String> rank = new TreeMap<>();
    rank.put(100, "wjj");
    rank.put(200, "jjw");    // TreeMap會自動進行排序
    1. 範圍查詢:比如找“分數在80-100的所有學生”
    SortedMap<Integer, String> sub = rank.subMap(80, 101);
    /*
        TreeMap就是實現了SortedMap接口的具體實現類
         SortedMap是一個接口,規定 有序Map 應該支持的一些功能
        1. subMap(fromKey, toKey)    獲取某個範圍的子視圖
        2. headMap(toKey)     獲取比某個key小的所有映射
        3. tailMap()    獲取比某個key大的所有映射
        4. firstKey()、lastKey()        獲取最大、最小key
    */

5、ConcurrentHashMap

為什麼使用這個?

  1. HashMap線程不安全,多線程環境下會出現問題(eg:死循環、數據丟失)
  2. Hashtable雖然線程安全,但是因為對方加了全表鎖(synchronized),併發性能很差
  • 底層:分段鎖(jdk7),CAS+synchronized(jdk8)
  • 特點:高併發環境下使用,性能遠高於Hashtable,其迭代器是弱一致性,其他線程更改Map,不會拋異常
  • 業務場景:

    1. 併發緩存:多線程同時讀寫緩存數據(用户session、token、臨時數據啥的)
    ConcurrentHashMap<String, Object> cache = new ConcurrentHashMap<>();
    cache.put("token", "xyz123");
    1. 統計併發管理訪問量:比如電商系統中統計商品的訪問次數
    2. 存放共享資源:比如多個線程共享的用户session信息

6、Hashteble

  • 底層:數組+鏈表
  • 特點:線程安全(方法上加synchronized,全),不允許null key和null value
  • 業務場景:

    1. 早期多線程程序:現在基本被ConcurrentHashMap替代
    2. 維護老項目會遇到,新開發基本用不上

7、WeakHashMap

  • 底層:key用弱引用存儲,GC發現key沒有強引用時,會自動回收對應的entry
  • 特點:適合做“臨時性緩存”
  • 業務場景:

    1. 緩存場景:避免緩存導致內存泄露,比如class loader緩存(當key沒人引用時,GC會自動清理)
    2. 圖片緩存:android中用過,用於圖片對象的緩存

8、IdentityHashMap

  • 底層:和HashMap類似,但key比較用 ==(地址比較) 而不是equals()
  • 業務場景:

    1. 對象唯一性映射:比如序列化時,判斷一個對象是否已經被處理過
    // 普通 HashMap 會認為兩個內容一樣的對象是同一個,但 IdentityHashMap 可以區分
    String a = new String("abc");
    String b = new String("abc");
    Map<String, String> map = new IndentityHashMap<>();
    map.put(a, "A");
    map.put(b, "B");
    System.out.println(map.size())    // 輸出2        而 HashMap 會輸出 1
    1. 特殊框架實現:一般業務開發幾乎不用
user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.