Java集合之Map接口

Map與List、Set接口不同,它是由一系列鍵值對組成的集合,提供了key到Value的映射。同時它也沒有繼承Collection。在Map中它保證了key與value之間的一一對應關係。也就是說一個key對應一個value,所以它不能存在相同的key值,當然value值可以相同。

Map接口體系

Map接口

Map接口提供了一系列操作鍵值對的方法,並且將鍵值對抽象爲獨立的對象,提供鍵值對維度的操作。

Map< K,V >接口
鍵值對映射
- clear() 清空map
- Java8 新增加compute(K key, BiFunction< ? super K, ? super V, ? extends V> remappingFunction) 對map中key爲對應k的value進行對應的函數式操作
- Java8 新增加computeIfAbsent(K key, Function< ? super K, ? extends V> mappingFunction) 當map中不存在key時,進行函數式操作,並將結果作爲value,K作爲key,放入map
- Java8 新增加computeIfPresent(K key, BiFunction< ? super K, ? super V,? extends V> remappingFunction)當map中存在key時,進行函數式操作,並將結果作爲value,K作爲key,更新對應的key-value
- containsKey(Object key) 是否包含對應的key
- containsValue(Object value) 是否包含對應的value
- entrySet() 返回map的Map.Entry< K,V >的Set
- Java8 新增加 forEach(BiConsumer< ? super K, ? super V> action) 爲每個Map包含的entry執行對應的二元函數式運算(BiConsumer表示二元函數式接口)
- get(Object key) 獲取key對應的value
- getOrDefault(Object key, V defaultValue)獲取key對應的value,沒有對應的key返回defaultValue
- isEmpty() Map是否爲空
- keySet() 返回Map的Key的集合(Set)
- Java8 新增加merge(K key, V value, BiFunction< ? super V, ? super V, ? extends V> remappingFunction)當map中不存在key時,進行函數式操作,並將結果作爲value,K作爲key,放入map
- put(K key, V value) 將一個鍵值對放入map
- putAll(Map< ? extends K,? extends V> m) 將一個子map放入當前map
- putIfAbsent(K key, V value) 僅當map中不存在對應的k-v時,將鍵值對放入map
- remove(Object key) 移除對應的k-v
- remove(Object key, Object value) 移除對應的k-v
- replace(K key, V value) 替換對應key的value
- replace(K key, V oldValue, V newValue) 替換對應的k-v的value
- replaceAll(BiFunction< ? super K, ? super V, ? extends V> function) 對每個鍵值對執行對應的二元函數式運算,並用運算結果替代value
- size() 返回map的keySet的size
- values() 返回map的value的集合

Map內部接口Entry,由於是內部接口,所以Entry默認是靜態的,只能訪問Map的靜態成員變量。

Map.Entry接口

Map.Entry< K,V > 接口
鍵值對對象
- getKey() 獲取鍵值對的key
- getValue() 獲取鍵值對的value
- setValue(V value) 替換鍵值對的value
- comparingByKey() 返回Map的key的比較器
- comparingByKey(Comparator< ? super K> cmp) 返回一個key的cmp比較器
- comparingByValue() 返回map的value的比較器
comparingByValue(Comparator< ? super V> cmp) 返回一個value的cmp比較器

HashMap< K , V>

HashMap is implemented as a hash table, and there is no ordering on keys or values.


HashMap doesn’t allow two identical elements. By default, the hashCode() and equals() methods implemented in the Object class are used. The default hashCode() method gives distinct integers for distinct objects, and the equals() method only returns true when two references refer to the same object.

HashMap是哈希表的一種實現,其內部是無序的,元素的存儲位置由其哈希值決定。
HashMap的鍵不允許相同,如果使用繼承了Object的類作爲鍵值,需要重寫equals方法,因爲Object類的equals方法只有當兩個引用指向同一個對象時才返回true,不從寫equals方法可能導致無法預知的錯誤。
HashMap繼承AbstractMap,AbstractMap類是Map接口的最小實現類。
HashMap的key和value都能爲null。
Java8中,當HashMap底層數組的某個鏈表過大時(長度大於8),會將這部分節點轉化爲TreeNode結構存儲。詳細瞭解可參考:http://blog.163.com/he_04143164/blog/static/27150310320173293218939/
HashMap是線程不安全的,多線程時使用CurrentHashMap,CurrentHashMap詳細解析請參考後續java.util.current包系列文章。
可以用Collections.synchronizedMap保證線程安全
Map m = Collections.synchronizedMap(new HashMap(…));
HashMap類
HashMap方法基本都是對於Map接口的實現,沒有額外的新增方法。

HashMap原理:
HashMap的鍵值對類Node實現了Map接口的Map.Entry接口,Node是一種單向鏈表,它有一個next屬性指向下一個節點。
Node節點以數組的形式存儲,entry的hash值決定它的存儲位置,如果當前位置還有其他的entry,則用鏈表存儲。如圖:
HashMap內部存儲結構

TreeMap< K , V>

TreeMaps are sorted by keys, the object for key has to be able to compare with each other, that’s why it has to implement Comparable interface.

TreeMap內部存儲是根據key值排序的,所以key的對象必須實現Comparable 接口。

TreeMap實現了SortedMap< K,V >接口,SortedMap提供了基於key的排序功能。
SortedMap< K,V > 接口
key是按照自然順序排序的(或者按照比較器排序)
comparator() 返回有序map的比較器
entrySet() 返回有序map的Entry集合
firstKey() 返回有序map的第一個key
headMap(K toKey) 返回toKey之前的子map
keySet() 返回有序map的key的集合
lastKey() 返回有序map的最後一個key
subMap(K fromKey, K toKey) 返回有序map從fromKey到toKey的子map,包括fromKey,不包括toKey
tailMap(K fromKey) 返回fromKey開始的子map,包括fromKey
values() 返回map的value的集合

TreeMap的內部是一顆紅黑樹,紅黑樹原理比較複雜,具體分析可參考:http://www.importnew.com/19074.html

Hashtable< K , V>
基本和HashMap沒有區別,除了所有的方法都加了synchronized關鍵字保證線程安全和不允許插入null之外(key和value都不能爲null)。

LinkedHashMap< K , V>
HashMap的子類,繼承了HashMap的方法和特性,同時可以保證元素的插入順序,即當插入A,B,C時,迭代器得到的的順序也是A,B,C.

LinkedHashMap的內部節點Entry繼承自HashMap.Node,額外新增加了Entry< K,V > before, after兩個屬性。before和after就是爲了記錄前一個插入的元素和記錄後一個插入的元素。

[1]: HashMap源碼分析
[2]: LinkedHashMap源碼詳解

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章