合并 Map<String, List<String> Java 8 Stream
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/36211405/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Merge Map<String, List<String> Java 8 Stream
提问by ypriverol
I would like to merge two Map with JAVA 8 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>>();
I try to use this implementation:
我尝试使用这个实现:
mapGlobal = Stream.of(mapGlobal, mapAdded)
.flatMap(m -> m.entrySet().stream())
.collect(Collectors.groupingBy(Map.Entry::getKey,
Collectors.mapping(Map.Entry::getValue,
Collectors.toList())
));
However, this implementation only create a result like:
但是,此实现只会创建类似的结果:
Map<String, List<Object>>
Map<String, List<Object>>
If one key is not contained in the mapGlobal
, it would be added as a new key with the corresponding List of String. If the key is duplicated in mapGlobal
and mapAdded
, both list of values will be merge as: A = {1, 3, 5, 7}
and B = {1, 2, 4, 6}
then A ∪ B = {1, 2, 3, 4, 5, 6, 7}
.
如果一个键不包含在 中mapGlobal
,它将作为一个新键与相应的字符串列表一起添加。如果钥匙被复制中mapGlobal
和mapAdded
,值的列表都将合并为:A = {1, 3, 5, 7}
和B = {1, 2, 4, 6}
然后A ∪ B = {1, 2, 3, 4, 5, 6, 7}
。
回答by Tunaki
You can do this by iterating over all the entries in mapAdded
and merging them into mapGlobal
.
您可以通过迭代中的所有条目mapAdded
并将它们合并到mapGlobal
.
The following iterates over the entries of mapAdded
by calling forEach(action)
where the action consumes the key and value of each entry. For each entry, we call merge(key, value, remappingFunction)
on mapGlobal
: this will either create the entry under the key k
and value v
if the key didn't exist or it will invoke the given remapping function if they already existed. This function takes the 2 lists to merge, which in this case, are first added to a TreeSet
to ensure both unique and sorted elements and converted back into a list:
下面mapAdded
通过调用forEach(action)
where 操作消耗每个条目的键和值来迭代 的条目。对于每个条目,我们叫merge(key, value, remappingFunction)
上mapGlobal
:这将要么创建键下的条目k
和值v
如果该键不存在,或者它会调用给定的重新映射功能,如果他们已经存在。此函数将 2 个列表合并,在这种情况下,首先将其添加到 aTreeSet
以确保唯一和已排序的元素并转换回列表:
mapAdded.forEach((k, v) -> mapGlobal.merge(k, v, (v1, v2) -> {
Set<String> set = new TreeSet<>(v1);
set.addAll(v2);
return new ArrayList<>(set);
}));
If you want to run that potentially in parallel, you can create a Stream pipeline by getting the entrySet()
and calling parallelStream()
on it. But then, you need to make sure to use a map that supports concurrency for mapGlobal
, like a ConcurrentHashMap
.
如果您想潜在地并行运行它,您可以通过获取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);
}));
回答by swapnil
Using foreach over Map can be used to merge given arraylist.
在 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;
}
回答by Sergei Veselev
The original implementation doesn't create result like Map<String, List<Object>>
, but Map<String, List<List<String>>>
. You need additional Stream pipeline on it to produce Map<String, List<String>>
.
原始实现不会创建类似的结果Map<String, List<Object>>
,但是Map<String, List<List<String>>>
。您需要额外的 Stream 管道来生成Map<String, List<String>>
.
回答by Jay
Using StreamEx
使用StreamEx
Map<String, List<String>> mergedMap =
EntryStream.of(mapGlobal)
.append(EntryStream.of(mapAdded))
.toMap((v1, v2) -> {
List<String> combined = new ArrayList<>();
combined.addAll(v1);
combined.addAll(v2);
return combined;
});
If you have even more maps to merge just append to the stream
如果您有更多地图要合并,只需附加到流
.append(EntryStream.of(mapAdded2))
.append(EntryStream.of(mapAdded3))