合并Map <String,List Java 8 Stream
我想将两个Map与JAVA 8 Stream合并:
Map<String, List> mapGlobal = new HashMap<String, List>(); Map<String, List> mapAdded = new HashMap<String, List>();
我尝试使用此实现:
mapGlobal = Stream.of(mapGlobal, mapAdded) .flatMap(m -> m.entrySet().stream()) .collect(Collectors.groupingBy(Map.Entry::getKey, Collectors.mapping(Map.Entry::getValue, Collectors.toList()) ));
但是,此实现仅创建如下结果:
Map<String, List>
如果mapGlobal
没有包含一个键,它将被添加为具有相应List of String的新键。 如果密钥在mapGlobal
和mapAdded
重复,则两个值列表将合并为: A = {1, 3, 5, 7}
并且B = {1, 2, 4, 6}
mapAdded
B = {1, 2, 4, 6}
然后A ∪ B = {1, 2, 3, 4, 5, 6, 7}
。
您可以通过迭代mapAdded
所有条目并将它们合并到mapGlobal
来完成此mapGlobal
。
下面通过调用forEach(action)
迭代mapAdded
的条目,其中action操作消耗每个条目的键和值。 对于每个条目,我们在mapGlobal
上调用merge(key, value, remappingFunction)
mapGlobal
:这将在键k
下创建条目,如果键不存在则值v
,或者如果它们已经存在则它将调用给定的重映射函数。 此函数将合并两个列表,在这种情况下,首先将它们添加到TreeSet
以确保唯一和已排序的元素并转换回列表:
mapAdded.forEach((k, v) -> mapGlobal.merge(k, v, (v1, v2) -> { Set set = new TreeSet<>(v1); set.addAll(v2); return new ArrayList<>(set); }));
如果要并行运行,可以通过获取entrySet()
并在其上调用parallelStream()
来创建Stream管道。 但是,您需要确保使用支持mapGlobal
并发的mapGlobal
,就像ConcurrentHashMap
。
ConcurrentMap> mapGlobal = new ConcurrentHashMap<>(); // ... mapAdded.entrySet().parallelStream().forEach(e -> mapGlobal.merge(e.getKey(), e.getValue(), (v1, v2) -> { Set set = new TreeSet<>(v1); set.addAll(v2); return new ArrayList<>(set); }));
使用foreach over Map合并映射到结果映射中的ArrayList值。
public Map> merge(Map> map1, Map> map2) { Map> map = new HashMap<>(); map.putAll(map1); map2.forEach((key , value) -> { //Get the value for key in map. ArrayList list = map.get(key); if (list == null) { map.put(key,value); } else { //Merge two list together ArrayList mergedValue = new ArrayList<>(value); mergedValue.addAll(list); map.put(key , mergedValue); } }); return map; }
原始实现不会创建Map
,但Map
。 您需要额外的Stream管道才能生成Map
。
您应该考虑使用Apache Commons
MultiValueMap
:
然后你可以写:
import org.apache.commons.collections4.map.MultiValueMap; MultiValueMap mapGlobal = new MultiValueMap<>(); MultiValueMap mapAdded = new MultiValueMap<>(); mapGlobal.putAll(mapAdded);