简体   繁体   English

转换地图 <K, V> 到地图 <V,List<K> &gt;

[英]Converting Map<K, V> to Map<V,List<K>>

I have map as below 我有如下地图

Map<String, String> values = new HashMap<String, String>();
values.put("aa", "20");
values.put("bb", "30");
values.put("cc", "20");
values.put("dd", "45");
values.put("ee", "35");
values.put("ff", "35");
values.put("gg", "20");

I want to create new map in the format Map<String,List<String>> , sample output will be as 我想以Map<String,List<String>>的格式创建新的地图,样本输出将为

"20" -> ["aa","cc","gg"]
"30" -> ["bb"]
"35" -> ["ee","ff"]     
"45" -> ["dd"]

I am able to do by iterating through entity 我可以通过迭代实体来做

Map<String, List<String>> output = new HashMap<String,List<String>>();
    for(Map.Entry<String, String> entry : values.entrySet()) {
        if(output.containsKey(entry.getValue())){
            output.get(entry.getValue()).add(entry.getKey());

        }else{
            List<String> list = new ArrayList<String>();
            list.add(entry.getKey());
            output.put(entry.getValue(),list);
          }
    }

Can this be done better using streams? 使用流可以做得更好吗?

groupingBy can be used to group the keys by the values. groupingBy可用于按值对键进行groupingBy If used without a mapping Collector , it will transform a Stream of map entries ( Stream<Map.Entry<String,String>> ) to a Map<String,List<Map.Entry<String,String>> , which is close to what you want, but not quite. 如果在没有使用mapping Collector ,将变换Stream映射条目(的Stream<Map.Entry<String,String>> )到Map<String,List<Map.Entry<String,String>> ,这是接近你想要什么,但不完全。

In order for the value of the output Map to be a List of the original keys, you have to chain a mapping Collector to the groupingBy Collector . 为了使输出Map的值成为原始键的List ,您必须将mapping CollectorgroupingBy Collector

Map<String,List<String>> output =
    values.entrySet()
          .stream()
          .collect(Collectors.groupingBy(Map.Entry::getValue,
                                         Collectors.mapping(Map.Entry::getKey,
                                                            Collectors.toList())));
System.out.println (output);

Output : 输出:

{45=[dd], 35=[ee, ff], 30=[bb], 20=[aa, cc, gg]}

Note that in Java 8, you can also do better without using streams using Map.forEach and Map.computeIfAbsent . 请注意,在Java 8中,如果不使用Map.forEachMap.computeIfAbsent使用流,也可以Map.computeIfAbsent This way, it is more concise than the old version with Map.Entry<String, String> , entry.getValue() , entry.getKey() etc. 这样,它比使用Map.Entry<String, String>entry.getValue()entry.getKey()等的旧版本更简洁。

So you don't have to compare the old Java-7 iteration to that Java-8 stream solution, but to this one. 因此,您不必将旧的Java-7迭代与Java-8流解决方案进行比较,而是将其与此进行比较。

values.forEach( (key,value)->
    groupBy.computeIfAbsent(value, x->new ArrayList<>())
           .add(key)
);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM