合并Map <string,set <string =“”>&gt;类型的两个地图

时间:2018-06-14 18:12:21

标签: lambda merge java-8 set java-stream

我有两个类型为Map<String, Set<String>>的地图,我需要根据每个地图的键进行合并。我使用的是Java 8.

我尝试了以下内容:

Map<String, Set<String>> collect = Stream.of(keyColumnValueAccumulator, keyColumnValues)
                .map(Map::entrySet)
                .flatMap(Collection::stream)
                .collect(Collectors.toMap(
                        Map.Entry::getKey, 
                        Map.Entry::getValue));

但是在运行时,这会产生一个“重复密钥”。错误。请有人帮忙吗?我还是Java 8和Stream API的新手

2 个答案:

答案 0 :(得分:2)

使用the merge function决定在发生密钥冲突时该怎么做:

例如,您可以将两个集合并为一个然后返回新的合并结果:

 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;}));

或者您可以保留第一个并丢弃第二个:

 Stream.of(keyColumnValueAccumulator, keyColumnValues)
           .map(Map::entrySet)
           .flatMap(Collection::stream)
           .collect(Collectors.toMap(
                 Map.Entry::getKey,
                 Map.Entry::getValue,
                (left, right) -> left);

或倒数:

Stream.of(keyColumnValueAccumulator, keyColumnValues)
           .map(Map::entrySet)
           .flatMap(Collection::stream)
           .collect(Collectors.toMap(
                 Map.Entry::getKey,
                 Map.Entry::getValue,
                (left, right) -> right);

或调用另一个函数来计算新值等等......

答案 1 :(得分:2)

您还可以使用Map::merge方法来避免重复键错误。

示例:

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;}));

在键碰撞的情况下,我们只是将两个集合累加为一个,但如果这不是所需的行为,您可以随时更改它或为remappingFunction创建自定义函数。