基於源碼的Java集合框架學習⑥ Map接口

接口 Map<K,V>

將鍵映射到值的對象。一個映射不能包含重複的鍵;每個鍵最多隻能映射一個值。

此接口代替 Dictionary 類,後者完全是一個抽象類,而不是一個接口。

Map 接口提供三種collection 視圖,允許以鍵集、值集合或鍵-值映射關係集的形式查看某個映射的內容。映射的順序 定義爲迭代器在映射的 collection 視圖中返回其元素的順序。某些映射實現可明確保證其順序,如 TreeMap 類;某些映射實現則不保證順序,如 HashMap 類。

注:將可變對象用作映射鍵時必須格外小心。當對象是映射中某個鍵時,如果以影響 equals 比較的方式更改了對象的值,則映射的行爲就不是特定的。此項禁止的一個特殊情況是不允許某個映射包含其自身作爲鍵。雖然允許某個映射包含其自身作爲值,但建議要格外小心:在這樣的映射上將無法再定義 equals 和 hashCode 方法。

所有通用的映射實現類應該提供兩個“標準的”構造方法:一個 void(無參數)構造方法,用於創建空映射,另一個是帶有 Map 類型單參數的構造方法,用於創建一個與其參數具有相同鍵-值映射關係的新映射。實際上,後一個構造方法允許用戶複製任意映射,生成所需類的一個等價映射。儘管無法強制執行該建議(因爲接口不能包含構造方法),但是 JDK 中所有通用的映射實現都遵從它。

該接口中包含的“破壞性”方法可修改其所操作的映射,如果此映射不支持該操作,則指定這些方法拋出 UnsupportedOperationException。如果是這樣,那麼在調用對該映射無效時,這些方法可能,但並不一定拋出 UnsupportedOperationException。例如,如果某個不可修改的映射(其映射關係是“重疊”的)爲空,則對該映射調用 putAll(Map) 方法時,可能但並不一定拋出異常。

某些映射實現對可能包含的鍵和值有所限制。例如,某些實現禁止空鍵和空值,而某些實現則對其鍵的類型有限制。嘗試插入不合格的鍵或值會拋出一個未經檢查的異常,通常是 NullPointerException 或 ClassCastException。試圖查詢是否存在不合格的鍵或值可能拋出異常,或者只是簡單地返回 false;某些實現將表現出前一種行爲,而某些實現則表現後一種。較爲常見的是,試圖對不合格的鍵或值執行操作且該操作的完成不會導致不合格的元素被插入映射中時,將可能拋出一個異常,也可能操作成功,這取決於實現本身。這樣的異常在此接口的規範中標記爲“可選”。

此接口是 Java Collections Framework 的成員。

Collections Framework 接口中的很多方法是根據 equals 方法定義的。例如,contains(Object key) 方法的規範聲明:“當且僅當此映射對於鍵 k 包含以下映射關係時才返回 true:(key==null ? k==null : key.equals(k))”。不 應將此規範解釋爲它暗指調用具有非空參數 key 的 Map.containsKey 會導致對任意的鍵 k 調用 key.equals(k)。可隨意對各種實現執行優化,只要避免調用 equals 即可,例如,通過首先比較兩個鍵的哈希碼(Object.hashCode() 規範保證哈希碼不相等的兩個對象不會相等)。較爲常見的是,各種 Collections Framework 接口的實現可隨意利用基礎 Object 方法的指定行爲,而不管實現程序認爲它是否合適。

 //方法 
 void clear() 
 從此映射中移除所有映射關係(可選操作)。 
 boolean containsKey(Object key) 
 如果此映射包含指定鍵的映射關係,則返回 true。 
 boolean containsValue(Object value) 
 如果此映射爲指定值映射一個或多個鍵,則返回 true。 
 Set<Map.Entry<K,V>> entrySet() 
 返回此映射中包含的映射關係的 set 視圖。 
 boolean equals(Object o) 
 比較指定的對象與此映射是否相等。 
 V get(Object key) 
 返回此映射中映射到指定鍵的值。 
 int hashCode() 
 返回此映射的哈希碼值。 
 boolean isEmpty() 
 如果此映射未包含鍵-值映射關係,則返回 true。 
 Set<K> keySet() 
 返回此映射中包含的鍵的 set 視圖。 
 V put(K key, V value) 
 將指定的值與此映射中的指定鍵相關聯(可選操作)。 
 void putAll(Map<? extends K,? extends V> t) 
 從指定映射中將所有映射關係複製到此映射中(可選操作)。 
 V remove(Object key) 
 如果存在此鍵的映射關係,則將其從映射中移除(可選操作)。 
 int size() 
 返回此映射中的鍵-值映射關係數。 
 Collection<V> values() 
 返回此映射中包含的值的 collection 視圖。 
 //嵌套類 
 static interface Map.Entry<K,V> 映射項(鍵-值對)。

Map提供接口分別用於返回 鍵集、值集或鍵-值映射關係集。

  1. entrySet()用於返回鍵-值集Set集合
  2. keySet()用於返回鍵集Set集合
  3. values()用戶返回值集Collection集合

因爲Map中不能包含重複的鍵;每個鍵最多隻能映射到一個值。所以,鍵-值集、鍵集都是Set,值集時Collection

Map提供了“鍵-值對”、“根據鍵獲取值”、“刪除鍵”、“獲取容量大小”等方法。

類 AbstractMap<K,V>

此類提供了 Map 接口的骨幹實現,從而最大限度地減少了實現此接口所需的工作。

要實現不可修改的映射,程序員只需擴展此類並提供 entrySet 方法的實現即可,該方法將返回映射的映射關係 Set 視圖。通常,返回的 Set 將依次在 AbstractSet 上實現。此 Set 不支持 add 或 remove 方法,其迭代器也不支持 remove 方法。

要實現可修改的映射,程序員還必須另外重寫此類的 put 方法(否則將拋出 UnsupportedOperationException),並且由 entrySet().iterator() 所返回的迭代器必須另外實現其 remove 方法。

 void clear() 
 從此映射中移除所有映射關係(可選操作)。 
protected  Object clone() 
 返回此 AbstractMap 實例的淺表複製:不克隆鍵和值本身。 
 boolean containsKey(Object key) 
 如果此映射包含指定鍵的映射關係,則返回 true。 
 boolean containsValue(Object value) 
 如果此映射將一個或多個鍵映射到該值,則返回 true。 
abstract  Set<Map.Entry<K,V>> entrySet() 
 返回包含在此映射中的映射關係的 Set 視圖。 
 boolean equals(Object o) 
 比較指定對象與此映射的相等性。 
 V get(Object key) 
 返回此映射將指定鍵映射到的值。 
 int hashCode() 
 返回此映射的哈希碼值。 
 boolean isEmpty() 
 如果此映射不包含任何鍵-值映射關係,則返回 true。 
 Set<K> keySet() 
 返回包含在此映射中的鍵的 Set 視圖。 
 V put(K key, V value) 
 將指定的值與此映射中的指定鍵關聯起來(可選操作)。 
 void putAll(Map<? extends K,? extends V> t) 
 將指定映射的所有映射關係複製到此映射中(可選操作)。 
 V remove(Object key) 
 如果此映射中存在此鍵的映射關係,則移除該映射關係(可選操作)。 
 int size() 
 返回此映射中鍵-值映射關係的數量。 
 String toString() 
 返回此映射的字符串表示形式。 
 Collection<V> values() 
 返回包含在此映射中的值的 collection 視圖。 

有兩個成員變量:

  1. keySet, 保存 map 中所有鍵的 Set
  2. values, 保存 map 中所有值的集合

他們都是 transient, volatile, 分別表示不可序列化、併發環境下變量的修改能夠保證線程可見性。需要注意的是 volatile 只能保證可見性,不能保證原子性,需要保證操作是原子性操作,才能保證使用 volatile 關鍵字的程序在併發時能夠正確執行。

 AbstractMap 也有兩個內部類:

  1. SimpleImmutableEntry, 表示一個不可變的鍵值對
  2. SimpleEntry, 表示可變的鍵值對

它們唯一的區別在於SimpleImmutableEntry的setValue會拋出UnsupportedOperationException。

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