合并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的新键。 如果密钥在mapGlobalmapAdded重复,则两个值列表将合并为: 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

https://commons.apache.org/proper/commons-collections/apidocs/org/apache/commons/collections4/map/MultiValueMap.html#putAll-K-java.util.Collection-

然后你可以写:

 import org.apache.commons.collections4.map.MultiValueMap; MultiValueMap mapGlobal = new MultiValueMap<>(); MultiValueMap mapAdded = new MultiValueMap<>(); mapGlobal.putAll(mapAdded);