合并Map <String,List <String> Java 8 Stream

ypr*_*rol 12 java collections lambda java-8 java-stream

我想将两个Map与JAVA 8 Stream合并:

Map<String, List<String>> mapGlobal = new HashMap<String, List<String>>();
Map<String, List<String>> mapAdded = new HashMap<String, List<String>>();
Run Code Online (Sandbox Code Playgroud)

我尝试使用此实现:

mapGlobal = Stream.of(mapGlobal, mapAdded)
                .flatMap(m -> m.entrySet().stream())
                .collect(Collectors.groupingBy(Map.Entry::getKey,
                        Collectors.mapping(Map.Entry::getValue,        
                                           Collectors.toList())
                ));
Run Code Online (Sandbox Code Playgroud)

但是,此实现仅创建如下结果:

Map<String, List<Object>>

如果未包含一个密钥mapGlobal,则将其添加为具有相应List字符串的新密钥.如果钥匙被复制中mapGlobalmapAdded,值的列表都将被合并为:A = {1, 3, 5, 7}B = {1, 2, 4, 6}然后A ? B = {1, 2, 3, 4, 5, 6, 7}.

Tun*_*aki 13

您可以通过迭代所有条目mapAdded并将它们合并到其中来完成此操作mapGlobal.

以下内容mapAdded通过调用forEach(action)操作消耗每个条目的键和值的位置来迭代.对于每个条目,我们叫merge(key, value, remappingFunction)mapGlobal:这将要么创建键下的条目k和值v如果该键不存在,或者它会调用给定的重映射功能,如果他们已经存在.此函数将合并两个列表,在这种情况下,首先将其添加到a TreeSet以确保唯一和已排序的元素并转换回列表:

mapAdded.forEach((k, v) -> mapGlobal.merge(k, v, (v1, v2) -> {
    Set<String> set = new TreeSet<>(v1);
    set.addAll(v2);
    return new ArrayList<>(set);
}));
Run Code Online (Sandbox Code Playgroud)

如果要并行运行,可以通过获取entrySet()并调用parallelStream()它来创建Stream管道.但是,您需要确保使用支持并发的映射mapGlobal,例如ConcurrentHashMap.

ConcurrentMap<String, List<String>> mapGlobal = new ConcurrentHashMap<>();
// ...
mapAdded.entrySet().parallelStream().forEach(e -> mapGlobal.merge(e.getKey(), e.getValue(), (v1, v2) -> {
    Set<String> set = new TreeSet<>(v1);
    set.addAll(v2);
    return new ArrayList<>(set);
}));
Run Code Online (Sandbox Code Playgroud)

  • @ypriverol是的你可以,我编辑了. (2认同)
  • 除非`mapGlobal`是`ConcurrentMap`,否则从并行流中改变它是不安全的. (2认同)

swa*_*nil 5

在 Map 上使用 foreach 可用于合并给定的数组列表。

    public Map<String, ArrayList<String>> merge(Map<String, ArrayList<String>> map1, Map<String, ArrayList<String>> map2) {
    Map<String, ArrayList<String>> map = new HashMap<>();
    map.putAll(map1);

    map2.forEach((key , value) -> {
        //Get the value for key in map.
        ArrayList<String> list = map.get(key);
        if (list == null) {
            map.put(key,value);
        }
        else {
            //Merge two list together
            ArrayList<String> mergedValue = new ArrayList<>(value);
            mergedValue.addAll(list);
            map.put(key , mergedValue);
        }
    });
    return map;
}
Run Code Online (Sandbox Code Playgroud)