Map
接口下面的Entry
接口。java
該接口,定義一個鍵值對實體接口。Map.entrySet
方法返回的 Set
集合中的實體就是實現這個 它。只有一種方法能夠得到 Map.Entry
對象的引用,那就是經過集合的迭代器。而且 Map.entry
只在迭代期間有效,更加準確的是意思是,若是在得到迭代器之後,修改了集合,那麼 Map.Entry
的行爲是未定義的1。除非調用 Map.Entry
的 setValue
設置下修改的值。ui
API
文檔中的這段話,說的讓我有點費解。修改集合之後,Map.Entry
的行爲是未定義的,LZ 作了實驗,發現並無觸發到什麼非法,未定義的操做。code
Map<String, String> stringMap = new HashMap<>(16); stringMap.put("key1", "value1"); stringMap.put("key2", "value2"); stringMap.put("key3", "value3"); stringMap.put("key4", "value4"); stringMap.put("key5", "value5"); stringMap.put("key6", "value6"); Iterator<Map.Entry<String, String>> iterator = stringMap.entrySet().iterator(); Map.Entry<String, String> next = iterator.next(); stringMap.remove(next.getKey()); stringMap.put(next.getKey(),"value7");
就如上面的代碼所示,在獲得 Entry
之後,對集合進行了修改,也沒有觸發什麼非法的狀態,拋出什麼異常來。這裏的未定義,實際上是一個很無懈可擊的答案,既然是未定義的,那麼它們作出的任何行爲,都是能夠被理解的,因此它沒拋出什麼異常,那也是對的,拋出異常也是對的,你不該該單方面的任認爲它應該怎樣怎樣,由於它是未定義,不一樣的實現有不一樣的反應。對象
並且這裏的合法與非法,是針對 Entry
的值來講,在你獲取之後,有人又修改了集合的內容,這時候你獲取的 Entry
的內容,也會隨之改變,可是你可能不知道集合被修改過,因此這裏的合法與非法,是 Entry
是否能夠再被信任的問題,因此想要修改值的時候,應該用 entry
的 setValue()
方法,顯示的去改。排序
返回實體對應的 key
。接口
可能拋出的異常 IllegalStateException
,這個異常能夠 選擇性 的實現。若是實現了,則異常的拋出條件:若是對應的 entry
已經被移除了,則拋出該異常。rem
好比,HashMap
的 Entry
就沒有實現拋出該異常:文檔
static class Node<K,V> implements Map.Entry<K,V> { ... public final K getKey() { return key; } ... }
而EnumMap
則實現了該異常,而且遵照了異常拋出條件:get
private class Entry implements Map.Entry<K,V> { ... public K getKey() { checkIndexForEntryUse(); return keyUniverse[index]; } ... private void checkIndexForEntryUse() { if (index < 0) throw new IllegalStateException("Entry was removed"); } }
返回 entry
實體對應的 value
。string
若是集合中此 entry
的映射關係已經被移除,即便是經過 iterator
的 remove
方法,getValue()
方法的返回值也是 未定義。所以,不一樣的實現,對此方法有不一樣的作法,HashMap
對其沒作什麼,正常返回值,即便映射關係被刪除了。EnumMap
則拋出異常。
可能拋出的異常 IllegalStateException
,這個異常能夠 選擇性 的實現。若是實現了,則異常的拋出條件:若是對應的 entry
已經被移除了,則拋出該異常。
替換當前 entry
的 value
爲傳進來的給定的 value
,(map
中對應的 value
也被改變)。若是集合中 entry
的映射關係已經被經過迭代器的 remove()
方法移除,則調用這個方法的行爲是 未定義 的。看具體的實現如何操做。一樣的 HashMap
對此行爲,返回正確的值。EnumMap
則拋出異常。
返回設置值以前,當前 entry
對應的值。
可能拋出的異常:
UnsupportedOperationException
:若是集合不支持 put
操做,則拋出此異常。ClassCastException
:若是傳入的參數,不能轉換存儲到集合中,則拋出此異常,類型轉換異常。NullPointerException
:若是集合不容許存入 null
,其傳入的參數確實是 null
,則拋出此異常。IllegalArgumentException
:若是傳入的值的某些屬性,阻止其存入集合中,則拋出此異常。IllegalStateException
:此異常可選擇是否實現。若是 entry
已經被移除了,則拋出此異常。將傳入的參數對象與當前的 entry
比較,若是傳入的對象也是一個 entry
類型,而且它們具備相同的映射關係,則返回 true
。
更確切的說,相同的映射關係,應該寫成下面的代碼: key
,value
分別相等。
(e1.getKey()==null ? e2.getKey()==null : e1.getKey().equals(e2.getKey())) && (e1.getValue()==null ? e2.getValue()==null: e1.getValue().equals(e2.getValue()))
這樣作之後,能夠確保 equals
方法在不一樣的 Map.Entry
實現以前都能正確的工做。
返回當前 entry
的哈希碼。entry
的哈希碼計算方法以下:
(e.getKey()==null ? 0 : e.getKey().hashCode()) ^ (e.getValue()==null ? 0 : e.getValue().hashCode())
這樣作,確保 e1.equals(e2)
時,e1.hashCode()==e2.hashCode()
,當前前提是,這個兩個 entry
的 KV
的 hashCode
方法一致 。
下面幾個方法是 1.8 添加進來的。屬於靜態方法
public static <K extends Comparable<? super K>, V> Comparator<Map.Entry<K,V>> comparingByKey() { return (Comparator<Map.Entry<K, V>> & Serializable) (c1, c2) -> c1.getKey().compareTo(c2.getKey()); }
返回一個 Comparator
,該比較器對 entry
的 key
進行 天然排序,即按照字典順序,0-9,a-z 。
返回的比較器,實現了 serializable
接口。代碼中 (Comparator<Map.Entry<K, V>> & Serializable)
是強轉的含義。強轉能夠這樣寫,轉爲兩者的結合,可是 &
後面必須是 接口 。
可能拋出的異常:NullPointerException
,若是比較的 entry
的 key
是 null
,則拋出此異常。
public static <K, V extends Comparable<? super V>> Comparator<Map.Entry<K,V>> comparingByValue() { return (Comparator<Map.Entry<K, V>> & Serializable) (c1, c2) -> c1.getValue().compareTo(c2.getValue()); }
返回一個 Comparator
,該比較器對 entry
的 key
進行 天然排序 。
返回的比較器,實現了 serializable
接口。
可能拋出的異常:NullPointerException
,若是比較的 entry
的 key
是 null
,則拋出此異常。
public static <K, V> Comparator<Map.Entry<K, V>> comparingByKey(Comparator<? super K> cmp) { Objects.requireNonNull(cmp); return (Comparator<Map.Entry<K, V>> & Serializable) (c1, c2) -> cmp.compare(c1.getKey(), c2.getKey()); }
返回一個比較器,該比較器對 entry
的 key
進行比較,根據傳入的比較器。若是傳入的比較器實現了 serializable
接口,那麼返回的比較器也一併實現該接口。
public static <K, V> Comparator<Map.Entry<K, V>> comparingByValue(Comparator<? super V> cmp) { Objects.requireNonNull(cmp); return (Comparator<Map.Entry<K, V>> & Serializable) (c1, c2) -> cmp.compare(c1.getValue(), c2.getValue()); }
返回一個比較器,該比較器對 entry
的 value
進行比較,根據傳入的比較器。若是傳入的比較器實現了 serializable
接口,那麼返回的比較器也一併實現該接口。
能夠參考下 codeRanch 上面的回答 。真是使人驚歎,上面關於這個疑問的討論,仍是十七年前的回答,當時的他們又是人幾何年呢。若是也如我同樣,那十七年過去了,如今也是不惑之年了。↩