我的地图如下
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");
我想以Map<String,List<String>>
格式创建新地图,样本输出将为
"20" -> ["aa","cc","gg"]
"30" -> ["bb"]
"35" -> ["ee","ff"]
"45" -> ["dd"]
我可以通过迭代实体
来做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);
}
}
使用流可以做得更好吗?
答案 0 :(得分:16)
groupingBy
可用于按值对键进行分组。如果在没有mapping
Collector
的情况下使用,它会将Stream
个地图条目(Stream<Map.Entry<String,String>>
)转换为Map<String,List<Map.Entry<String,String>>
,这与您想要的接近,但不完全。
为了使输出Map
的值为原始密钥的List
,您必须将mapping
Collector
链接到groupingBy
} 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);
输出:
{45=[dd], 35=[ee, ff], 30=[bb], 20=[aa, cc, gg]}
答案 1 :(得分:4)
请注意,在Java 8中,您还可以在不使用Map.forEach
和Map.computeIfAbsent
的流的情况下做得更好。这样,它比Map.Entry<String, String>
,entry.getValue()
,entry.getKey()
等旧版本更简洁。
因此,您不必将旧的Java-7迭代与Java-8流解决方案进行比较,而是将其与此进行比较。
values.forEach( (key,value)->
groupBy.computeIfAbsent(value, x->new ArrayList<>())
.add(key)
);