Map
接口下面的Entry
接口。java
该接口,定义一个键值对实体接口。Map.entrySet
方法返回的 Set
集合中的实体就是实现这个 它。只有一种方法能够得到 Map.Entry
对象的引用,那就是经过集合的迭代器。而且 Map.entry
只在迭代期间有效,更加准确的是意思是,若是在得到迭代器之后,修改了集合,那么 Map.Entry
的行为是未定义的1。除非调用 Map.Entry
的 setValue
设置下修改的值。web
API
文档中的这段话,说的让我有点费解。修改集合之后,Map.Entry
的行为是未定义的,LZ 作了实验,发现并无触发到什么非法,未定义的操做。svg
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
之后,对集合进行了修改,也没有触发什么非法的状态,抛出什么异常来。这里的未定义,实际上是一个很无懈可击的答案,既然是未定义的,那么它们作出的任何行为,都是能够被理解的,因此它没抛出什么异常,那也是对的,抛出异常也是对的,你不该该单方面的任认为它应该怎样怎样,由于它是未定义,不一样的实现有不一样的反应。ui
并且这里的合法与非法,是针对 Entry
的值来讲,在你获取之后,有人又修改了集合的内容,这时候你获取的 Entry
的内容,也会随之改变,可是你可能不知道集合被修改过,因此这里的合法与非法,是 Entry
是否能够再被信任的问题,因此想要修改值的时候,应该用 entry
的 setValue()
方法,显示的去改。spa
返回实体对应的 key
。3d
可能抛出的异常 IllegalStateException
,这个异常能够 选择性 的实现。若是实现了,则异常的抛出条件:若是对应的 entry
已经被移除了,则抛出该异常。code
好比,HashMap
的 Entry
就没有实现抛出该异常:xml
static class Node<K,V> implements Map.Entry<K,V> { ... public final K getKey() { return key; } ... }
而EnumMap
则实现了该异常,而且遵照了异常抛出条件:对象
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
。排序
若是集合中此 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 上面的回答 。真是使人惊叹,上面关于这个疑问的讨论,仍是十七年前的回答,当时的他们又是人几何年呢。若是也如我同样,那十七年过去了,如今也是不惑之年了。 ↩︎