Map.Entry 接口

Map.Entry

Map 接口下面的 Entry 接口。java

該接口,定義一個鍵值對實體接口。Map.entrySet 方法返回的 Set 集合中的實體就是實現這個 它。只有一種方法能夠得到 Map.Entry 對象的引用,那就是經過集合的迭代器。而且 Map.entry 只在迭代期間有效,更加準確的是意思是,若是在得到迭代器之後,修改了集合,那麼 Map.Entry 的行爲是未定義的1。除非調用 Map.EntrysetValue 設置下修改的值。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 是否能夠再被信任的問題,因此想要修改值的時候,應該用 entrysetValue() 方法,顯示的去改。排序


K getKey()

返回實體對應的 key接口

可能拋出的異常 IllegalStateException ,這個異常能夠 選擇性 的實現。若是實現了,則異常的拋出條件:若是對應的 entry 已經被移除了,則拋出該異常。rem

好比,HashMapEntry 就沒有實現拋出該異常:文檔

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");
            }
    }

V getValue()

返回 entry 實體對應的 valuestring

若是集合中此 entry 的映射關係已經被移除,即便是經過 iteratorremove 方法,getValue() 方法的返回值也是 未定義。所以,不一樣的實現,對此方法有不一樣的作法,HashMap 對其沒作什麼,正常返回值,即便映射關係被刪除了。EnumMap 則拋出異常。

可能拋出的異常 IllegalStateException ,這個異常能夠 選擇性 的實現。若是實現了,則異常的拋出條件:若是對應的 entry 已經被移除了,則拋出該異常。


V setValue(V value)

替換當前 entryvalue 爲傳進來的給定的 value ,(map 中對應的 value 也被改變)。若是集合中 entry 的映射關係已經被經過迭代器的 remove() 方法移除,則調用這個方法的行爲是 未定義 的。看具體的實現如何操做。一樣的 HashMap 對此行爲,返回正確的值。EnumMap 則拋出異常。

返回設置值以前,當前 entry 對應的值。

可能拋出的異常:

  1. UnsupportedOperationException :若是集合不支持 put 操做,則拋出此異常。
  2. ClassCastException:若是傳入的參數,不能轉換存儲到集合中,則拋出此異常,類型轉換異常。
  3. NullPointerException:若是集合不容許存入 null ,其傳入的參數確實是 null ,則拋出此異常。
  4. IllegalArgumentException:若是傳入的值的某些屬性,阻止其存入集合中,則拋出此異常。
  5. IllegalStateException :此異常可選擇是否實現。若是 entry 已經被移除了,則拋出此異常。

boolean equals(Object o)

將傳入的參數對象與當前的 entry 比較,若是傳入的對象也是一個 entry 類型,而且它們具備相同的映射關係,則返回 true

更確切的說,相同的映射關係,應該寫成下面的代碼: keyvalue 分別相等。

(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 實現以前都能正確的工做。


int hashCode()

返回當前 entry 的哈希碼。entry 的哈希碼計算方法以下:

(e.getKey()==null   ? 0 : e.getKey().hashCode())
    ^
    (e.getValue()==null ? 0 : e.getValue().hashCode())

這樣作,確保 e1.equals(e2) 時,e1.hashCode()==e2.hashCode() ,當前前提是,這個兩個 entryKVhashCode 方法一致 。


下面幾個方法是 1.8 添加進來的。屬於靜態方法

comparingByKey()

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 ,該比較器對 entrykey進行 天然排序,即按照字典順序,0-9,a-z

返回的比較器,實現了 serializable 接口。代碼中 (Comparator<Map.Entry<K, V>> & Serializable) 是強轉的含義。強轉能夠這樣寫,轉爲兩者的結合,可是 & 後面必須是 接口

可能拋出的異常:NullPointerException ,若是比較的 entrykeynull,則拋出此異常。


comparingByValue( )

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 ,該比較器對 entrykey進行 天然排序

返回的比較器,實現了 serializable 接口。

可能拋出的異常:NullPointerException ,若是比較的 entrykeynull,則拋出此異常。


comparingByKey(Comparator<? super K> cmp)

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());
        }

返回一個比較器,該比較器對 entrykey 進行比較,根據傳入的比較器。若是傳入的比較器實現了 serializable 接口,那麼返回的比較器也一併實現該接口。


comparingByValue(Comparator<? super V> cmp)

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());
        }

返回一個比較器,該比較器對 entryvalue 進行比較,根據傳入的比較器。若是傳入的比較器實現了 serializable 接口,那麼返回的比較器也一併實現該接口。



  1. 能夠參考下 codeRanch 上面的回答 。真是使人驚歎,上面關於這個疑問的討論,仍是十七年前的回答,當時的他們又是人幾何年呢。若是也如我同樣,那十七年過去了,如今也是不惑之年了。

相關文章
相關標籤/搜索