一、獲取key和value
獲取key:map.keySet(),獲取map中所有的key,返回一個Set集合儲存所有的鍵;
獲取value:Map.values()或者map.entrySet()
-
Map.values(),方法用來獲取 Map 集合中的所有value,將值存放在一個Set集合中
-
map.entrySet()✅,同時獲取map的key和value,只需要查詢一次;然後for迴圈key,根據key獲取value
二、常用map之間的區別和使用場景
2.1. hashMap, hashtable,linkedHashMap,treeMap之間的區別
(1)hashMap: 以鍵值對盡心儲存,執行緒不安全,無序,可以允許一個null鍵和多個null,可以透過鍵直接獲取對應值,所以查詢效率高
(2) concurrentHashMap:
(3) linkedHashMap: 它是hashmap的子集,在繼承hashmap的同時新增了一個排序欄位,記錄插入的順序,透過for迴圈可以有序的輸出
(4) treemap: 它實現了sortedmap,所以可以進行集合排序輸出,預設是透過key進行的升序進行排序,也可以自定義進行排序
(5) hashtable(最好不用): 它也是透過鍵值對進行儲存,無序,但是他是執行緒安全的,絕大多數方法使用synchronized修飾,不允許null鍵和null值,一般用於多執行緒併發情況,但是在最新的程式碼中最好不使用,在單執行緒中使用hashmap效率快,在多執行緒併發下,使用ConcurrentHashMap效率更快
2.2. 使用場景
當程式是單執行緒,且對集合輸出的排序沒有確切要求時使用hashMap
當程式是多執行緒併發情況,並且不需要排序,最好使用ConcurrentHashMap
當程式中需要先進先出時,我們則要使用linkedHashMap
當程式中需要對於集合進行特殊化排序時,我們即可使用TreeMap
對比項 |
HashMap |
ConcurrnetHashMap |
HashTable(不用) |
---|---|---|---|
執行緒安全 |
非執行緒安全 |
執行緒安全 |
執行緒安全 |
效率 |
最高 |
高 |
低 |
鍵和值 |
允許為null |
允許為null |
都不允許 |
使用選擇 |
普通map |
需要執行緒安全 |
2.3 HashMap和HashTable
- HashMap是非執行緒安全的,HashTable是執行緒安全的(內部的方法基本都經過synchronized修飾,其實是對物件加鎖,鎖住的都是物件整體,當Hashtable的大小增加到一定的時候,效能會急劇下降,因為迭代時需要被鎖定很長的時間)
- HashMap的鍵和值都允許有null存在,而HashTable則都不行。
- 因為執行緒安全、雜湊效率的問題,HashMap效率比HashTable的要高(HashTable效率低所以不怎麼使用)。
- HashMap預設初始化陣列的大小為16,擴容時乘2,使用位運算取得雜湊,效率高於取模;jdk8之後,如果連結串列的長度大於8,這個單向連結串列就會轉換為紅黑樹;如果連結串列長度小於6位,就會從紅黑樹轉換為連結串列。陣列擴容時,擴容的大小是原有陣列的2倍;HashTable為11,擴容時為乘2加1,都是素數和奇數,這樣取模雜湊結果更均勻。
三、ConcurrentHashMap
3.1 執行緒安全
ConcurrentHashMap 的執行緒安全指的是:提供的原子性讀寫操作是執行緒安全的, 也就是put()、get()操作是執行緒安全的。即在ConcurrentHashMap的內部使用CAS保證了更新操作的原子性,在同一時間只有一個執行緒能夠完成對值的更新。
3.2 ConcurrentHashMap為什麼高效?
Hashtable低效主要是因為所有訪問Hashtable的執行緒都爭奪一把鎖。如果容器有很多把鎖,每一把鎖控制容器中的一部分資料,那麼當多個執行緒訪問容器裡的不同部分的資料時,執行緒之前就不會存在鎖的競爭,這樣就可以有效的提高併發的訪問效率。這也正是ConcurrentHashMap使用的分段鎖技術。將ConcurrentHashMap容器的資料分段儲存,每一段資料分配一個Segment(鎖),當執行緒佔用其中一個Segment時,其他執行緒可正常訪問其他段資料。
3.3 方法
-
put()
-
get()
-
size()
-
computeIfAbsent:Value不存在時才計算
-
computeIfPresent:Value存在時才計算
-
compute:計算並更新值
https://wizardforcel.gitbooks.io/modern-java/content/ch6.html
http://blog.tanpeng.net/2017/07/13/map-compute/
3.4 問題
1、get+put操作並非原子操作,會導致執行緒不安全
問題描述:https://blog.csdn.net/weixin_46539949/article/details/121114944
解決:synchronized或者computeIfAbsent
- 1、synchronized程式碼塊鎖住map(效率低 )
- 2、使用computeIfAbsent
四、HashMap
4.1方法
-
getOrDefault() 方法獲取指定 key 對應對 value,如果找不到 key ,則返回設定的預設值。語法為hashmap.getOrDefault(Object key, V defaultValue)
五、ImmutableMap
可以更簡潔地建立Map物件並賦值;物件建立後不可變。
5.1 特點
1.對不可靠的客戶程式碼庫來說,它使用安全,可以在未受信任的類庫中安全的使用這些物件
2.執行緒安全的:immutable物件在多執行緒下安全,沒有競態條件
3.不需要支援可變性, 可以儘量節省空間和時間的開銷. 所有的不可變集合實現都比可變集合更加有效的利用記憶體 (analysis)
4.可以被使用為一個常量,並且期望在未來也是保持不變的
5.2 使用
ImmutableMap.of("a", 1, "b", 2);
2、使用Builder類建立
Map<String,Object> immutableMap = new ImmutableMap.Builder<String,Object>() .put("k1","v1") .put("k2","v2") .build();