前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java Map通过值来获取键的正确姿势

Java Map通过值来获取键的正确姿势

作者头像
明明如月学长
发布2021-08-27 16:30:17
5.5K0
发布2021-08-27 16:30:17
举报
文章被收录于专栏:明明如月的技术专栏

本文将展示3种,Java中通过Map的值获取其键的方式。本文将讨论不同方法的优缺点。如果想学习Map的更多内容,参见The Java HashMap Under the Hood 

一、Java API

方法1: 迭代方式

Java 集合框架的Map类提供了 entrySet()方法,该方法返回Map的键值对Entry对象。

该方法的思路是,迭代Entry集合,当值和传入的value匹配时,返回对应的key。

代码语言:javascript
复制
public  K getKey(Map map, V value) {
    for (Entry entry : map.entrySet()) {
        if (entry.getValue().equals(value)) {
            return entry.getKey();
        }
    }
    return null;
}

然而,有可能有多个键对应同一个值。因此我们找到匹配的值时需要将其加入到Set中,Set包含所有待查找的Key。

代码语言:javascript
复制
public  Set getKeys(Map map, V value) {
    Set keys = new HashSet<>();
    for (Entry entry : map.entrySet()) {
        if (entry.getValue().equals(value)) {
            keys.add(entry.getKey());
        }
    }
    return keys;
}

尽管这种方式非常简单而直接,但是采用这种方式即使经过几次迭代就可以找到所有的键也得迭代完整个Map。

方法2: 函数式查找

我可以采用Java8的Lambda表达式,来更灵活和可读地方式实现类似功能。

我们可以使用Stream的map函数,返回满足条件的Entry的键。

代码语言:javascript
复制
public  Stream keys(Map map, V value) {
    return map
      .entrySet()
      .stream()
      .filter(entry -> value.equals(entry.getValue()))
      .map(Map.Entry::getKey);
}

返回键的Stream是为了方便后续多样化的处理方式。调用者或许只需要一个或者所有指向某个值的键。因为Stream是惰性求值的,调用方可以根据需要控制迭代的次数。

另外,使用合适的收集器(collector)可以将返回值转换成需要的集合形式。

代码语言:javascript
复制
Stream keyStream1 = keys(capitalCountryMap, "South Africa");
String capital = keyStream1.findFirst().get();
 
Stream keyStream2 = keys(capitalCountryMap, "South Africa");
Set capitals = keyStream2.collect(Collectors.toSet());

二、利用Apache Commons Collections库

如果需要多次调用上述方法来查询某个值对应的键,会造成不必要的多次迭代。

在这种场景下,维护另外一个值指向键的map就很有必要了,因为这样可以使通过值获取键的时间复杂度降为常数级。

Apache 的Commons Collections 库里提供了双向Map叫BidiMap。该类提供了getKey函数来根据值获取键。

代码语言:javascript
复制
BidiMap capitalCountryMap = new DualHashBidiMap<>();
capitalCountryMap.put("Berlin", "Germany");
capitalCountryMap.put("Cape Town", "South Africa");
String capitalOfGermany = capitalCountryMap.getKey("Germany");

然而,BidiMap强制键值对时一一对应关系。如果键值对的值已经存在map中,你调用put方法,将会移除旧的entry对象。换句话说,该类是依据值来更新键的。

另外,该功能需要大量内存来存放反向map。

更多关于BidiMap的详细内容,参考:https://www.baeldung.com/commons-collections-bidi-map

三、使用 Google Guava

我们还可以使用Google Guava包下的一个叫BiMap的双向map。该类提供了Inverser()函数来获取值-键对。

代码语言:javascript
复制
HashBiMap capitalCountryMap = HashBiMap.create();
capitalCountryMap.put("Berlin", "Germany");
capitalCountryMap.put("Cape Town", "South Africa");
String capitalOfGermany = capitalCountryMap.inverse().get("Germany");

和BidiMap一样,BiMap也不允许通过相同的值获取多个键。如果你这么做,会得到ava.lang.IllegalArgumentException异常。

不用说,BiMap也使用了大量内存来存储反向map。如果你对BiMap感兴趣,可以戳这里:https://www.baeldung.com/guava-bimap

结论

本文简要讨论了通过键获取Map的值的方式。每种方法都有各自优缺点。我们要根据使用场景来选择最合适的方式。

完整源代码参见这里:https://github.com/eugenp/tutorials/tree/master/java-collections-maps

英文原文:https://www.baeldung.com/java-map-key-from-value

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018/12/17 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、Java API
    • 方法1: 迭代方式
      • 方法2: 函数式查找
      • 二、利用Apache Commons Collections库
      • 三、使用 Google Guava
      • 结论
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档