jdk1.8.0_45源码解读——Map接口和AbstractMap抽象类的实现
jdk1.8.0_45源碼解讀——Map接口和AbstractMap抽象類的實現
一、 Map架構
如上圖:
(01) Map 是映射接口,Map中存儲的內容是鍵值對(key-value)。
(02) AbstractMap 是繼承于Map的抽象類,它實現了Map中的大部分API。其它Map的實現類可以通過繼承AbstractMap來減少重復編碼。
(03) SortedMap 是繼承于Map的接口。SortedMap中的內容是排序的鍵值對,排序的方法是通過比較器(Comparator)。
(04) NavigableMap 是繼承于SortedMap的接口。相比于SortedMap,NavigableMap有一系列的導航方法;如"獲取大于/等于某對象的鍵值對"、“獲取小于/等于某對象的鍵值對”等等。
(05) TreeMap 繼承于AbstractMap,且實現了NavigableMap接口;因此,TreeMap中的內容是“有序的鍵值對”!
(06) HashMap 繼承于AbstractMap,但沒實現NavigableMap接口;因此,HashMap的內容是“鍵值對,但不保證次序”!
(07) Hashtable 雖然不是繼承于AbstractMap,但它繼承于Dictionary(Dictionary也是鍵值對的接口),而且也實現Map接口;因此,Hashtable的內容也是“鍵值對,也不保證次序”。但和HashMap相比,Hashtable是線程安全的,而且它支持通過Enumeration去遍歷。
(08) WeakHashMap 繼承于AbstractMap。它和HashMap的鍵類型不同,WeakHashMap的鍵是“弱鍵”。
?
二、 Map接口
1. Map.Entry<K, V>的結構
映射項(鍵-值對)。Map.entrySet() 方法返回映射的 collection 視圖,其中的元素屬于此類。獲得映射項引用的唯一 方法是通過此 collection 視圖的迭代器來實現。這些 Map.Entry 對象僅在迭代期間有效;更確切地講,如果在迭代器返回項之后修改了底層映射,則某些映射項的行為是不確定的,除了通過 setValue 在映射項上執行操作之外。
K getKey(); //返回此項中對應的鍵值 V getValue(); //返回此項中對應的值 V setValue(V value); //用指定的值替換與此項對應的值 boolean equals(Object o); //比較指定對象與此項的相等性 int hashCode(); //返回此項的哈希碼?
2. Map接口
將鍵映射到值的對象。一個映射不能包含重復的鍵;每個鍵最多只能映射到一個值。
Map 接口提供三種collection 視圖,允許以鍵集、值集或鍵-值映射關系集的形式查看某個映射的內容。映射順序 定義為迭代器在映射的 collection 視圖上返回其元素的順序。某些映射實現可明確保證其順序,如 TreeMap 類;另一些映射實現則不保證順序,如 HashMap 類。
注:將可變對象用作映射鍵時必須格外小心。當對象是映射中某個鍵時,如果以影響 equals 比較的方式更改了對象的值,則映射的行為將是不確定的。此項禁止的一種特殊情況是不允許某個映射將自身作為一個鍵包含。雖然允許某個映射將自身作為值包含,但請格外小心:在這樣的映射上 equals 和 hashCode 方法的定義將不再是明確的。
public interface Map<K,V> {int size();boolean isEmpty();boolean containsKey(Object key);boolean containsValue(Object value);V get(Object key);V put(K key, V value);V remove(Object key);void putAll(Map<? extends K, ? extends V> m);void clear(); Set<K> keySet();Collection<V> values();//返回此映射中包含的映射關系的 set 視圖Set<Map.Entry<K, V>> entrySet();boolean equals(Object o);int hashCode(); }?
三、AbstractMap抽象類
1. AbstractMap.SimpleEntry<K, V>的結構
SimpleEntry<K, V>是維護鍵和值的 Entry??梢允褂?setValue() 方法更改值。此類簡化了構建自定義映射實現的過程。例如,可以使用 Map.entrySet().toArray 方法方便地返回 SimpleEntry實例數組。
public static class SimpleEntry<K,V>implements Entry<K,V>, java.io.Serializable{private static final long serialVersionUID = -8499721149061103585L;private final K key;private V value;//創建一個項,它表示從指定鍵到指定值的映射關系public SimpleEntry(K key, V value) {this.key = key;this.value = value;}//創建一個項,它表示的映射關系與指定的項相同public SimpleEntry(Entry<? extends K, ? extends V> entry) {this.key = entry.getKey();this.value = entry.getValue();}//返回對應于此項的鍵public K getKey() {return key;}//返回對應于此項的值public V getValue() {return value;}//用指定值替換對應于此項的值,并返回舊值public V setValue(V value) {V oldValue = this.value;this.value = value;return oldValue;}//相等性檢測,包括null值private static boolean eq(Object o1, Object o2) {return o1 == null ? o2 == null : o1.equals(o2);}//比較指定對象與此項的相等性public boolean equals(Object o) {if (!(o instanceof Map.Entry))return false;Map.Entry<?,?> e = (Map.Entry<?,?>)o;return eq(key, e.getKey()) && eq(value, e.getValue());}//返回此映射項的哈希值:key值的哈希碼與value值的哈希碼按位異或的結果public int hashCode() {return (key == null ? 0 : key.hashCode()) ^(value == null ? 0 : value.hashCode());}//返回此映射項的 String表示形式:key=valuepublic String toString() {return key + "=" + value;}} View Code?
2.AbstractMap.SimpleImmutableEntry<K,V>的結構
SimpleImmutableEntry<K,V>是維護不可變的鍵和值的 Entry,不支持setValue()方法。方便用于在返回線程安全的鍵-值映射關系的方法。
public static class SimpleImmutableEntry<K,V>implements Entry<K,V>, java.io.Serializable{private static final long serialVersionUID = 7138329143949025153L;private final K key;private final V value;//創建一個項,它表示從指定鍵到指定值的映射關系public SimpleImmutableEntry(K key, V value) {this.key = key;this.value = value;}//創建一個項,它表示的映射關系與指定項相同public SimpleImmutableEntry(Entry<? extends K, ? extends V> entry) {this.key = entry.getKey();this.value = entry.getValue();}//返回對應于此項的鍵public K getKey() {return key;}//返回對應于此項的值public V getValue() {return value;}//該方法僅拋出UnsupportedOperationException,表明該Entry不支持setValue方法public V setValue(V value) {throw new UnsupportedOperationException();}//比較指定對象與此項的相等性public boolean equals(Object o) {if (!(o instanceof Map.Entry))return false;Map.Entry<?,?> e = (Map.Entry<?,?>)o;return eq(key, e.getKey()) && eq(value, e.getValue());}//返回此映射項的哈希值:key值的哈希碼與value值的哈希碼按位異或的結果public int hashCode() {return (key == null ? 0 : key.hashCode()) ^(value == null ? 0 : value.hashCode());}//返回此映射項的 String表示形式:key=valuepublic String toString() {return key + "=" + value;}} View Code?
3. AbstractMap抽象類
AbstractMap類提供 Map接口的骨干實現,以最大限度地減少實現此接口所需的工作。
要實現不可修改的映射,編程人員只需擴展此類并提供 entrySet() 方法的實現即可,該方法將返回映射的映射關系 set視圖。通常,返回的 set 將依次在 AbstractSet 上實現。此 set不支持 add() 或 remove() 方法,其迭代器也不支持 remove() 方法。
要實現可修改的映射,編程人員必須另外重寫此類的put() 方法(否則將拋出 UnsupportedOperationException),entrySet().iterator() 返回的迭代器也必須另外實現其 remove() 方法。
public abstract class AbstractMap<K,V> implements Map<K,V> {//構造函數protected AbstractMap() {}//返回此映射中的鍵-值映射關系數public int size() {return entrySet().size();}//如果此映射未包含鍵-值映射關系,則返回 true。public boolean isEmpty() {return size() == 0;}//如果鍵值對<key,value>集合中包含指定的value值,則返回turepublic boolean containsValue(Object value) {//entrySet()返回此映射中包含的映射關系的Set視圖Iterator<Entry<K,V>> i = entrySet().iterator(); //Map中允許value值為null,故分兩種情況考慮if (value==null) {while (i.hasNext()) {Entry<K,V> e = i.next();if (e.getValue()==null)return true;}} else {while (i.hasNext()) {Entry<K,V> e = i.next();if (value.equals(e.getValue()))return true;}}return false;}//如果鍵值對<key,value>集合中包含指定的key值,則返回turepublic boolean containsKey(Object key) {//entrySet()返回此映射中包含的映射關系的Set視圖Iterator<Map.Entry<K,V>> i = entrySet().iterator();//Map中只允許有唯一一個null的key值,故分兩種情況考慮if (key==null) {while (i.hasNext()) {Entry<K,V> e = i.next();if (e.getKey()==null)return true;}} else {while (i.hasNext()) {Entry<K,V> e = i.next();if (key.equals(e.getKey()))return true;}}return false;}//返回指定鍵所映射的值;如果此映射不包含該鍵的映射關系,則返回 nullpublic V get(Object key) {Iterator<Entry<K,V>> i = entrySet().iterator();if (key==null) {while (i.hasNext()) {Entry<K,V> e = i.next();if (e.getKey()==null)return e.getValue();}} else {while (i.hasNext()) {Entry<K,V> e = i.next();if (key.equals(e.getKey()))return e.getValue();}}return null;}//將指定的值與此映射中的指定鍵關聯public V put(K key, V value) {throw new UnsupportedOperationException();}/*** 如果存在一個鍵的映射關系,則將其從此映射中移除。并返回以前與key關聯的值;如果沒有key的映射關系,則返回null** 注意,如果 entrySet()返回的集合所調用的迭代器不支持 remove方法,并且此映射包含指定鍵的映射關系,* 則此實現將拋出 UnsupportedOperationException。 */public V remove(Object key) {Iterator<Entry<K,V>> i = entrySet().iterator();Entry<K,V> correctEntry = null; //用于指向給定鍵值對應的映射關系//找到指定鍵的映射關系,并賦值給correctEntryif (key==null) {while (correctEntry==null && i.hasNext()) {Entry<K,V> e = i.next();if (e.getKey()==null)correctEntry = e;}} else {while (correctEntry==null && i.hasNext()) {Entry<K,V> e = i.next();if (key.equals(e.getKey()))correctEntry = e;}}V oldValue = null;if (correctEntry !=null) {oldValue = correctEntry.getValue(); //得到以前與key關聯的值i.remove(); //運用迭代器中的remove()方法來對得到的鍵值對項進行移除工作 }return oldValue;}//從指定Map中將所有映射關系<key,value>復制到此映射中public void putAll(Map<? extends K, ? extends V> m) {for (Map.Entry<? extends K, ? extends V> e : m.entrySet())put(e.getKey(), e.getValue());}//從此映射中移除所有映射關系public void clear() {entrySet().clear();}//用volatile修飾的變量,線程在每次使用變量的時候,都會讀取變量最后修改后的值transient volatile Set<K> keySet; //Map中key值的唯一性決定鍵值集合的視圖類型為Settransient volatile Collection<V> values; //Map中value值的可重復性決定值集合的視圖類型為Collection//返回此映射中包含的鍵的 Set視圖public Set<K> keySet() {if (keySet == null) {keySet = new AbstractSet<K>() {public Iterator<K> iterator() {return new Iterator<K>() {private Iterator<Entry<K,V>> i = entrySet().iterator();public boolean hasNext() {return i.hasNext();}public K next() {return i.next().getKey(); //得到鍵值 }public void remove() {i.remove();}};}public int size() {return AbstractMap.this.size();}public boolean isEmpty() {return AbstractMap.this.isEmpty();}public void clear() {AbstractMap.this.clear();}public boolean contains(Object k) {return AbstractMap.this.containsKey(k);}};}return keySet;}//返回此映射中包含的值的 Collection視圖public Collection<V> values() {if (values == null) {values = new AbstractCollection<V>() {public Iterator<V> iterator() {return new Iterator<V>() {private Iterator<Entry<K,V>> i = entrySet().iterator();public boolean hasNext() {return i.hasNext();}public V next() {return i.next().getValue(); //得到value值 }public void remove() {i.remove();}};}public int size() {return AbstractMap.this.size();}public boolean isEmpty() {return AbstractMap.this.isEmpty();}public void clear() {AbstractMap.this.clear();}public boolean contains(Object v) {return AbstractMap.this.containsValue(v);}};}return values;}//返回此映射中包含的映射關系的 Set 視圖public abstract Set<Entry<K,V>> entrySet();//比較指定對象與此映射的相等性public boolean equals(Object o) {//如果給定對象也是一個映射并且兩個映射表示相同的映射關系,則返回trueif (o == this)return true;//檢查指定的對象是否為映射關系if (!(o instanceof Map))return false;Map<?,?> m = (Map<?,?>) o; //強制類型轉換//檢查指定的對象是否是一個大小與此映射相等的映射if (m.size() != size())return false;//在此映射 entrySet()返回的collection上進行迭代,并檢查指定的映射是否包含此映射所包含的每個映射關系try {Iterator<Entry<K,V>> i = entrySet().iterator();while (i.hasNext()) {Entry<K,V> e = i.next();K key = e.getKey(); //此映射的key值V value = e.getValue(); //此映射的value值if (value == null) {if (!(m.get(key)==null && m.containsKey(key)))return false;} else {if (!value.equals(m.get(key)))return false;}}} catch (ClassCastException unused) {return false;} catch (NullPointerException unused) {return false;}return true;}//返回此映射的哈希值//Map的哈希碼被定義為該映射的 entrySet()視圖中每個條目的哈希碼之和。這確保了 m1.equals(m2)對于任意兩個映射m1和m2都意味著 m1.hashCode()==m2.hashCode()public int hashCode() {int h = 0;Iterator<Entry<K,V>> i = entrySet().iterator();while (i.hasNext())h += i.next().hashCode();return h;}//返回此映射的字符串表示形式:{key1=value1}, {key1=value1}, ...public String toString() {Iterator<Entry<K,V>> i = entrySet().iterator();if (! i.hasNext()) //Map為nullreturn "{}";StringBuilder sb = new StringBuilder();sb.append('{');for (;;) {Entry<K,V> e = i.next();K key = e.getKey();V value = e.getValue();sb.append(key == this ? "(this Map)" : key);sb.append('=');sb.append(value == this ? "(this Map)" : value);if (! i.hasNext())return sb.append('}').toString();sb.append(',').append(' ');}}//返回此 AbstractMap 實例的淺表副本:不復制鍵和值本身protected Object clone() throws CloneNotSupportedException {AbstractMap<?,?> result = (AbstractMap<?,?>)super.clone();result.keySet = null;result.values = null;return result;} } View Code?
轉載于:https://www.cnblogs.com/CherishFX/p/4740113.html
總結
以上是生活随笔為你收集整理的jdk1.8.0_45源码解读——Map接口和AbstractMap抽象类的实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 架构知识整理
- 下一篇: Android获取相册图片