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
"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. 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.
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<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]}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With