通过Value获取Map中的键值Key的四种方法
1 简介
我们都知道Map
是存放键值对<Key,Value>
的容器,知道了Key值,使用方法Map.get(key)
能快速获取Value值。然而,有的时候我们需要反过来获取,知道Value值,求Key值。
本文将用实例介绍四种方法,通过传入Value值,获取得到Key值。
2 四种方法
2.1 循环法
循环法就是通过遍历Map里的Entry,一个个比较,把符合条件的找出来。会有三种情况:
(1)找到一个值
(2)找到多个值
(3)找不到
具体代码如下:
@Test
public void loop() {
Map<String, Integer> map = ImmutableMap.of("A", 1, "B", 2, "C", 3, "D", 2);
//找到一个值
assertEquals("A", getKeyByLoop(map, 1));
//找到多个值
assertEquals(ImmutableSet.of("B", "D"), getKeysByLoop(map, 2));
//找不到
assertEquals(null, getKeyByLoop(map, 4));
}
private <K, V> K getKeyByLoop(Map<K, V> map, V value) {
for (Map.Entry<K, V> entry : map.entrySet()) {
if (Objects.equals(entry.getValue(), value)) {
return entry.getKey();
}
}
return null;
}
private <K, V> Set<K> getKeysByLoop(Map<K, V> map, V value) {
Set<K> set = Sets.newHashSet();
for (Map.Entry<K, V> entry : map.entrySet()) {
if (Objects.equals(entry.getValue(), value)) {
set.add(entry.getKey());
}
}
return set;
}
想特别说的一点是,在对比是否相等的时候,使用了Objects.equals(a, b)
方法,而不是用a.equals(b)
方法。这样可以避免空指针异常。
2.2 Stream方法
Stream
总是在多种集合操作上都能提供优雅直观的方法,易写易理解。通过一个过滤器,即可把满足相等条件的值取出来,代码如下:
@Test
public void stream() {
Map<String, Integer> map = ImmutableMap.of("A", 1, "B", 2, "C", 3, "D", 2);
assertEquals(ImmutableSet.of("B", "D"), getKeysByStream(map, 2));
}
private <K, V> Set<K> getKeysByStream(Map<K, V> map, V value) {
return map.entrySet()
.stream()
.filter(kvEntry -> Objects.equals(kvEntry.getValue(), value))
.map(Map.Entry::getKey)
.collect(Collectors.toSet());
}
2.3 Guava的BiMap
Google的Guava
提供了BiMap
这样一个双向Map,调用inverse()
方法会返回一个反向的关联的BiMap
,然后便可以通过get()
方法获取key值了。
代码如下:
@Test
public void guava() {
BiMap<String, Integer> biMap = HashBiMap.create();
biMap.put("A", 1);
biMap.put("B", 2);
biMap.put("C", null);
biMap.put("D", 4);
assertEquals("D", biMap.inverse().get(4));
}
需要注意的是,BiMap
作为一个双向的Map
,它不能存储多对一的关系;而HashMap
是可以的。其实很好理解,因为是双向的,所以即要满足Key
值的唯一性,也要满足Value
值的唯一性。如果往里存放同样的Value,会抛异常:java.lang.IllegalArgumentException: value already present
。
2.4 Apache Commons Collections的BidiMap
类似地,Apache Commons Collections
也提供了双向Map的类BidiMap
,它也是维持一对一的关系,不能多对一。它提供了getKey(value)
方法返回Key值。代码如下:
@Test
public void apacheCommons() {
BidiMap<String, Integer> bidiMap = new DualHashBidiMap<>();
bidiMap.put("A", 1);
bidiMap.put("B", 2);
bidiMap.put("C", null);
bidiMap.put("D", 4);
assertEquals("D", bidiMap.getKey(4));
}
与Guava的BiMap
不同的是,当存放同样的Value时,它不会抛异常,而是覆盖原有的数据。
3 总结
本文介绍了四种通过Value值获取Map中的Key值的方法,分别是循环法、Stream、Guava、Apache Commons Collections,这四种方法类似但不尽相同。
(1)循环法和使用Stram本质上都是要遍历的,如果一个Map经常需要反向取Key值,则不建议使用,可以考虑Guava和Apache Commons提供的双向Map;
(2)双向Map其实是一种空间换取时间的思想,虽然能较快的找到满足条件的Key值,但它也使用了更多的空间来储存双向Map;
(3)双向Map并不支持多对一的关系。
如何选择,就看具体需求来取舍了。
通过Value获取Map中的键值Key的四种方法的更多相关文章
- 【Java必修课】通过Value获取Map中的键值Key的四种方法
1 简介 我们都知道Map是存放键值对<Key,Value>的容器,知道了Key值,使用方法Map.get(key)能快速获取Value值.然而,有的时候我们需要反过来获取,知道Value ...
- jsp页面使用el 按key获取map中的对应值
jsp页面使用el 按key获取map中的对应值 转自:<jsp页面使用el 按key获取map中的对应值>地址:http://blog.csdn.net/baple/article/de ...
- for in 循环获取json中的键(key)与值(value)
一 .for in 循环 1.获取json中的键(key)与值(value): var data = {name:'张三',age:'20岁',sex:'男'}; for (var a in data ...
- android中退出当前应用程序的四种方法
android中退出当前应用程序的四种方法 [IT168 技术]Android程序有很多Activity,比如说主窗口A,调用了子窗口B,如果在B中直接finish(), 接下里显示的是A.在B中如何 ...
- Java中取小数点后两位(四种方法)
摘自http://irobot.iteye.com/blog/285537 Java中取小数点后两位(四种方法) 一 Long是长整型,怎么有小数,是double吧 java.text.D ...
- Map:containsKey、containsValue 获取Map集合的键值的 值
get(Object key) 返回与指定键关联的值: containsKey(Object key) 如果Map包含指定键的隐射,则返回true: containsValue(Object valu ...
- 实现对多维数组按照某个键值排序的两种方法(array_multisort和array_sort)
实现对多维数组按照某个键值排序的两种解决方法(array_multisort和array_sort): 第一种:array_multisort()函数对多个数组或多维数组进行排序. //对数组$ ...
- python QQTableView中嵌入复选框CheckBox四种方法
搜索了一下,QTableView中嵌入复选框CheckBox方法有四种: 第一种不能之前显示,必须双击/选中后才能显示,不适用. 第二种比较简单,通常用这种方法. 第三种只适合静态显示静态数据用 第四 ...
- JS获取URL中参数值(QueryString)的4种方法分享<转>
方法一:正则法 复制代码代码如下: function getQueryString(name) { var reg = new RegExp('(^|&)' + name + '=([^ ...
随机推荐
- 证明xcosx无周期
假设\(xcos\,x\)有周期,依据周期函数的规律,可得 \[ \begin{aligned} xcos\,x & = (x+T)cos\,(x+T) \\ & = (x+T)cos ...
- 〈四〉ElasticSearch的认识:基础原理的补充
目录 想想我们漏了什么 回顾 补回 集群的建立 集群发现机制 配置文件 健康状态 补充: 小节总结 分片的管理 梳理 分片的均衡分配 主副分片的排斥 容错性: 数据路由 对于集群健康状态的影响 小节总 ...
- 利用基本数据封装类(如:Integer,Float)等实现数据类型转换
/** * 利用基本数据封装类进行数据类型转换 * @author dyh * */ public class TypeConversion { public static void main(Str ...
- [JavaScript] 《JavaScript高级程序设计》笔记
1.|| 和 && 这两个逻辑运算符和c#是类似的,都是惰性的计算 a() || b() 若a()为真返回a()的结果,此时b()不计算: a()为假则返回b() a() &am ...
- Mysql Hash索引和B-Tree索引区别(Comparison of B-Tree and Hash Indexes)
上篇文章中说道,Mysql中的Btree索引和Hash索引的区别,没做展开描述,今天有空,上Mysql官方文档找到了相关答案,看完之后,针对两者的区别做如下总结: 引用维基百科上的描述,来解释一下这两 ...
- 小白学 Python(1):开篇
人生苦短,我用 Python 引言 大家好,可能大家都对我比较熟悉了,不熟悉请去面壁(现在熟悉一下也来得及)~ 简单做一个自我介绍,我是极客挖掘机的唯一作者,一位油腻的 Java 程序员[臭鸡蛋什么的 ...
- Spring Boot2 系列教程(十三)Spring Boot 中的全局异常处理
在 Spring Boot 项目中 ,异常统一处理,可以使用 Spring 中 @ControllerAdvice 来统一处理,也可以自己来定义异常处理方案.Spring Boot 中,对异常的处理有 ...
- 树莓派(4B)Linux + .Net Core嵌入式-初始化环境(一)
一.树莓派简单介绍 二.软&件准备 硬件:树莓派4B主机.电源线.TF卡&TF读卡器.PC 软件:win32diskimager(用于烧系统到TF卡).Xshell或Windows T ...
- 虚拟机桥接模式下将虚拟IP设为静态IP
一:虚拟机设置桥接模式 1.进入虚拟机设置中将网络适配器设置成桥接模式,如下图 2.编辑--虚拟网络编辑器--选择桥接 3.如上图中桥接模式下的桥接到--将自动改成与本机匹配的虚拟网卡,本机虚拟网卡查 ...
- 浅谈celery的坑
celery celery的使用以及在Django中的配置,不详细介绍,主要记录在Django中使用的坑点. 坑点 时区问题 celery默认的时区是世界标准时间,比东八区慢了8个小时,如果发布定时任 ...