Map.Entry 接口
Map.Entry
Map
接口下面的Entry
接口。
该接口,定义一个键值对实体接口。Map.entrySet
方法返回的 Set
集合中的实体就是实现这个 它。只有一种方法可以获得 Map.Entry
对象的引用,那就是通过集合的迭代器。并且 Map.entry
只在迭代期间有效,更加准确的是意思是,如果在获得迭代器以后,修改了集合,那么 Map.Entry
的行为是未定义的[1]。除非调用 Map.Entry
的 setValue
设置下修改的值。
API
文档中的这段话,说的让我有点费解。修改集合以后,Map.Entry
的行为是未定义的,LZ 做了实验,发现并没有触发到什么非法,未定义的操作。
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()
方法,显示的去改。
K getKey()
返回实体对应的 key
。
可能抛出的异常 IllegalStateException
,这个异常可以 选择性 的实现。如果实现了,则异常的抛出条件:如果对应的 entry
已经被移除了,则抛出该异常。
比如,HashMap
的 Entry
就没有实现抛出该异常:
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");
}
}
V getValue()
返回 entry
实体对应的 value
。
如果集合中此 entry
的映射关系已经被移除,即使是通过 iterator
的 remove
方法,getValue()
方法的返回值也是 未定义。因此,不同的实现,对此方法有不同的做法,HashMap
对其没做什么,正常返回值,即使映射关系被删除了。EnumMap
则抛出异常。
可能抛出的异常 IllegalStateException
,这个异常可以 选择性 的实现。如果实现了,则异常的抛出条件:如果对应的 entry
已经被移除了,则抛出该异常。
V setValue(V value)
替换当前 entry
的 value
为传进来的给定的 value
,(map
中对应的 value
也被改变)。如果集合中 entry
的映射关系已经被通过迭代器的 remove()
方法移除,则调用这个方法的行为是 未定义 的。看具体的实现如何操作。同样的 HashMap
对此行为,返回正确的值。EnumMap
则抛出异常。
返回设置值之前,当前 entry
对应的值。
可能抛出的异常:
UnsupportedOperationException
:如果集合不支持put
操作,则抛出此异常。ClassCastException
:如果传入的参数,不能转换存储到集合中,则抛出此异常,类型转换异常。NullPointerException
:如果集合不允许存入null
,其传入的参数确实是null
,则抛出此异常。IllegalArgumentException
:如果传入的值的某些属性,阻止其存入集合中,则抛出此异常。IllegalStateException
:此异常可选择是否实现。如果entry
已经被移除了,则抛出此异常。
boolean equals(Object o)
将传入的参数对象与当前的 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
实现之前都能正确的工作。
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()
,当前前提是,这个两个 entry
的 KV
的 hashCode
方法一致 。
下面几个方法是 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
,该比较器对 entry
的 key
进行 自然排序,即按照字典顺序,0-9,a-z 。
返回的比较器,实现了 serializable
接口。代码中 (Comparator<Map.Entry<K, V>> & Serializable)
是强转的含义。强转可以这样写,转为二者的结合,但是 &
后面必须是 接口 。
可能抛出的异常:NullPointerException
,如果比较的 entry
的 key
是 null
,则抛出此异常。
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
,该比较器对 entry
的 key
进行 自然排序 。
返回的比较器,实现了 serializable
接口。
可能抛出的异常:NullPointerException
,如果比较的 entry
的 key
是 null
,则抛出此异常。
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());
}
返回一个比较器,该比较器对 entry
的 key
进行比较,根据传入的比较器。如果传入的比较器实现了 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());
}
返回一个比较器,该比较器对 entry
的 value
进行比较,根据传入的比较器。如果传入的比较器实现了 serializable
接口,那么返回的比较器也一并实现该接口。
可以参考下 codeRanch 上面的回答 。真是令人惊叹,上面关于这个疑问的讨论,还是十七年前的回答,当时的他们又是人几何年呢。如果也如我一样,那十七年过去了,现在也是不惑之年了。 ↩︎
Map.Entry 接口的更多相关文章
- 介绍map.entry接口
Map是java中的接口,Map.Entry是Map的一个内部接口.java.util.Map.Entry接口主要就是在遍历map的时候用到. Map提供了一些常用方法,如keySet().entry ...
- java.util.Map.Entry接口
java.util.Map.Entry接口主要就是在遍历map的时候用到,给你个例子:package test;import java.util.*;import java.util.Map.Entr ...
- Map接口,Map.Entry,hashMap类,TreeMap类,WeakHashMap。
Collection接口之前接触过,每次保存的对象是一个对象,但是在map中保存的是一对对象,是以key->value形式保存的. 定义: public interface Map<K,V ...
- Java集合Map接口与Map.Entry学习
Java集合Map接口与Map.Entry学习 Map接口不是Collection接口的继承.Map接口用于维护键/值对(key/value pairs).该接口描述了从不重复的键到值的映射. (1) ...
- 遍历Map集合:java.util.Map.Entry、KeySet两种方式
遍历Map集合的两种方式: 1.用KeySet Map.keySet(),返回一个存放所有key的set集合,通过遍历集合,根据key值取出所有的value值. Map<String,Strin ...
- Map集合的遍历(利用entry接口的方式)
核心思想: 调用map集合中的方法entrySet()将集合中的映射关系存放在Set集合中. 迭代Set集合 获取出的Set集合的元素是映射关系对象 通过映射关系对象方法的getKey(),getVa ...
- java的Map及Map.Entry解析
Map<K,V>是以键-值对存储的(key-value), 而Entry<K,V>是Map中的一个接口,Map.Entry<K,V>接口主要用于获取.比较 key和 ...
- java Map及Map.Entry详解
Map是java中的接口,Map.Entry是Map的一个内部接口. Map提供了一些常用方法,如keySet().entrySet()等方法. keySet()方法返回值是Map中key值的集合:e ...
- Map.Entry
Map.Entry Map是java中的接口,Map.Entry是Map的一个内部接口. Map提供了一些常用方法,如keySet().entrySet()等方法,keySet()方法返回值是Map中 ...
随机推荐
- mysql主从配置详解(图文)
最近工作不是很忙,把以前整理的mysql数据库的主从配置过程记录一下,有不足之处,请各位多多纠正指教 #环境配置#master IP:192.168.46.137 slave IP:192.168.4 ...
- containerd与kubernetes集成
kubernetes集群三步安装 概念介绍 cri (Container runtime interface) cri is a containerd plugin implementation of ...
- LeetCode——540. Single Element in a Sorted Array
题目:Given a sorted array consisting of only integers where every element appears twice except for one ...
- HomeKit智能球泡
产品名称: 智能LED灯泡调光调色 接入苹果HomeKit家庭(无需网关).天猫精灵.小爱.小度.Google.ALEXA 产品价格:9.9 本产品是针对HomeKit的产品,没有iphone手机,配 ...
- 使用selenium进行爬取掘金前端小册的数据
Selenium 简介 百度百科介绍: Selenium [1] 是一个用于Web应用程序测试的工具.Selenium测试直接运行在浏览器中,就像真正的用户在操作一样.支持的浏览器包括IE(7, 8, ...
- 深入理解 linux磁盘顺序写、随机写
一.前言 ● 随机写会导致磁头不停地换道,造成效率的极大降低:顺序写磁头几乎不用换道,或者换道的时间很短 ● 本文来讨论一下两者具体的差别以及相应的内核调用 二.环境准备 组件 版本 OS Ubunt ...
- css3实现loading效果--当页面加载过程中显示Loading的进度条,全部加载完成之后进度条消失
一个页面等图片资源全部加载完成,会需要很长时间,用户体验会很差,所以我们需要loading来掩盖这个漫长的过程! emmm,定时器?写个定时器还要清除,万一造成内存泄露?定时器之间还会互相影响,呼呼呼 ...
- Javasrcipt中从一个url或者从一个字符串中获取参数值得方法
从url中获取参数值是che程序开发过程中的常用需求,偶然得闲,便抽空研究了一下javasrcipt下,获取参数的办法(JAVA中也类似). 首先看url的规范: URL组成:protocol :// ...
- forward(转发)和redirect(重定向)的区别
在学习Servlet和JSP时,经常会使用到forward和redirect,我们先来看这两者在Servlet中的调用方式: 1.forward request.getRequestDispatche ...
- 【redis】redis应用场景,缓存的各种问题
如果你还不知道redis的基本命令与基本使用方法,请看 [redis]redis基础命令学习集合 缓存 redis还有另外一个重要的应用领域——缓存 引用来自网友的图解释缓存在架构中的位置 默认情况下 ...