Reputation: 162
I have two maps of type Map<String, Set<String>>
that I need to merge based on the key of each. I'm using Java 8.
I have tried the following:
Map<String, Set<String>> collect = Stream.of(keyColumnValueAccumulator, keyColumnValues)
.map(Map::entrySet)
.flatMap(Collection::stream)
.collect(Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue));
But at runtime this results in a 'Duplicate Key' error. Please can someone help? I'm still quite new to Java 8 and the Stream API
Upvotes: 2
Views: 2447
Reputation: 56423
You could also use the Map::merge method to avoid the duplicate key error.
Example:
Map<String, Set<String>> accumulator = new HashMap<>();
firstMap.forEach((k, v) -> accumulator.merge(k, v, (prev, cur) -> {prev.addAll(cur); return prev;}));
secondMap.forEach((k, v) -> accumulator.merge(k, v, (prev, cur) -> {prev.addAll(cur); return prev;}));
In the case of a key collision, we simply accumulate the two sets into one, but if this is not the desired behaviour you can always alter it or create a custom function for the remappingFunction
.
Upvotes: 3
Reputation: 56423
Use the merge function to decide what to do in case of a key collision:
for example, you could merge the two sets into one then return the new merged result:
Stream.of(keyColumnValueAccumulator, keyColumnValues)
.map(Map::entrySet)
.flatMap(Collection::stream)
.collect(Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue,
(left, right) -> {left.addAll(right); return left;}));
or you can keep the first and discard the second:
Stream.of(keyColumnValueAccumulator, keyColumnValues)
.map(Map::entrySet)
.flatMap(Collection::stream)
.collect(Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue,
(left, right) -> left);
or the reciprocal:
Stream.of(keyColumnValueAccumulator, keyColumnValues)
.map(Map::entrySet)
.flatMap(Collection::stream)
.collect(Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue,
(left, right) -> right);
or call another function to compute the new value and so forth...
Upvotes: 2