Map不由Collection接口派生站辉,Map提供key到value的映射唁毒。一個Map中不能包含相同的key蘑辑,每個key只能映射一個 value。與Map接口相關(guān)的部分UML類圖如下:
其具體實現(xiàn)類主要有:HashMap浇冰、LinkedHashMap贬媒、TreeMap、HashTable肘习。
HashMap
1际乘、允許null鍵/值。
2漂佩、非線程安全脖含。
3、不保證有序(比如插入的順序)仅仆、也不保證序不隨時間變化器赞。
LinkedHashMap
1垢袱、LinkedHashMap是基于HashMap實現(xiàn)的墓拜,它繼承了HashMap。
2请契、內(nèi)部節(jié)點(diǎn)是雙向的咳榜,從而保證了迭代順序是插入的順序夏醉;如果accessOrder為true,則維護(hù)了最近訪問的順序涌韩。
3畔柔、LinkedHashMap會在節(jié)點(diǎn)插入、節(jié)點(diǎn)訪問臣樱、節(jié)點(diǎn)移除后做一些事情靶擦,即更新鏈表,把最近訪問的放到最后雇毫。
TreeMap
1玄捕、通過Comparator對象,來保持我們想要維護(hù)的key的大小順序棚放。
2枚粘、使用平衡二叉樹——紅黑樹來存儲元素,紅黑樹的特性決定了它的查詢飘蚯、插入馍迄、刪除操作的時間復(fù)雜度均為O(log n)。
HashTable
1局骤、Hashtable不允許key或者value使用null值攀圈。
2、Hashtable的大部分方法做了同步峦甩,因此是線程安全的量承。
3、key的hash算法以及index的計算方法跟HashMap不同穴店。
同步問題
1撕捍、HashMap、LinkedHashMap泣洞、TreeMap都是非線程安全的忧风,如果在多線程中使用,可以通過 Collections.synchronizedMap(Map<K,V> m) 來實現(xiàn)線程安全球凰,其內(nèi)部是通過 synchronized 關(guān)鍵字來修飾方法來達(dá)到同步的目的狮腿。
2、HashMap 提供了對應(yīng)的 ConcurrentHashMap 這個線程安全的類呕诉,重要通過以下三個方面來達(dá)到高并發(fā)的目的(參考):
1缘厢、用分離鎖實現(xiàn)多個線程間的更深層次的共享訪問。
- 在 ConcurrentHashMap 中甩挫,線程對映射表做讀操作時贴硫,一般情況下不需要加鎖就可以完成,對容器做結(jié)構(gòu)性修改的操作才需要加鎖。
- 使用 Segment 類(繼承于 ReentrantLock 類)英遭,加鎖操作是針對(鍵的 hash 值對應(yīng)的)某個具體的 Segment间护,鎖定的是該 Segment 而不是整個 ConcurrentHashMap。因為插入鍵 / 值對操作只是在這個 Segment 包含的某個桶中完成挖诸,不需要鎖定整個ConcurrentHashMap汁尺。此時,其他寫線程對另外 15 個Segment 的加鎖并不會因為當(dāng)前線程對這個 Segment 的加鎖而阻塞多律。同時痴突,所有讀線程幾乎不會因本線程的加鎖而阻塞(除非讀線程剛好讀到這個 Segment 中某個 HashEntry 的 value 域的值為 null,此時需要加鎖后重新讀取該值)狼荞。
2苞也、用 HashEntery 對象的不變性來降低執(zhí)行讀操作的線程在遍歷鏈表期間對加鎖的需求。
3粘秆、通過對同一個 Volatile 變量的寫 / 讀訪問如迟,協(xié)調(diào)不同線程間讀 / 寫操作的內(nèi)存可見性。(在 value 字段添加 volatile 修飾符)
通過減小請求同一個鎖的頻率和盡量減少持有鎖的時間 攻走,使得 ConcurrentHashMap 的并發(fā)性相對于 HashTable 和用同步包裝器包裝的 HashMap有了質(zhì)的提高殷勘,so,優(yōu)先使用 ConcurrentHashMap昔搂。