Reputation: 93
I have a Stream< Map< K, V > >
and I'm trying to merge those maps together, but preserve duplicate values in a list, so the final type would be Map< K, List<V> >
. Is there a way to do this? I know the toMap
collector has a binary function to basically choose which value is returned, but can it keep track of the converted list?
i.e.
if a
is a Stream< Map< String, Int > >
a.flatMap(map -> map.entrySet().stream()).collect(
Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (val1, val2) -> ??
);
Upvotes: 7
Views: 1785
Reputation: 11949
Use groupingBy: see the javadoc, but in your case it should be something like that:
a.flatMap(map -> map.entrySet().stream())
.collect(
Collectors.groupingBy(
Map.Entry::getKey,
HashMap::new,
Collectors.mapping(Map.Entry::getValue, toList())
)
);
Or:
a.map(Map::entrySet).flatMap(Set::stream)
.collect(Collectors.groupingBy(
Map.Entry::getKey,
Collectors.mapping(Map.Entry::getValue, toList())
)
);
Upvotes: 11
Reputation: 4959
This is a bit wordier than the groupingBy solution, but I just wanted to point out that it is also possible to use toMap (as you initially set out to do) by providing the merge function:
a.flatMap(map -> map.entrySet().stream()).collect(
Collectors.toMap(Map.Entry::getKey,
entry -> {
List<Integer> list = new ArrayList<>();
list.add(entry.getValue());
return list;
},
(list1, list2) -> {
list1.addAll(list2);
return list1;
}));
Upvotes: 0