[英]Merge list of maps into a single map by summing values
我有一个类值:
public class Values {
private int count;
private int values;
}
以及Map<String, Values>
类型的多个映射的Map<String, Values>
Map<String, Values> map1 = new HashMap<>();
map1 .put("aaa", new Values(1, 10));
map1 .put("bbb", new Values(5, 50));
map1 .put("ccc", new Values(2, 30));
Map<String, Values> map2= new HashMap<>();
map2.put("aaa", new Values(2, 20));
map2.put("bbb", new Values(3, 50));
map2.put("ccc", new Values(3, 10));
List<Map<String, Values>> list = Arrays.asList(map1, map2);
地图中可以有任意数量的地图和任意数量的条目,但地图的键始终相同,只有值可以不同。 为清晰起见,我的示例仅包含2个地图,每个地图仅包含3个条目。
我想获得一个具有相同键的单个映射,并使用Values对象作为对象中每个“count”和每个“value”的总和,如下所示:
{
aaa= {
count = 3,
value = 30
},
bbb= {
count = 8,
value = 100
},
ccc= {
count = 6,
value = 40
}
}
我试图使用Streams API实现这一点,但我陷入困境:
public static Map<String, Values> mergeMaps(List<Map<String, Values>> maps) {
return maps.stream()
.flatMap(m -> m.entrySet().stream()) ...?
}
如何通过键对每个条目进行分组,并将每个计数和每个值加到一个映射中?
先感谢您。
您可以使用toMap
收集器使用合并功能收集Stream
的条目。
public static Map<String, Values> mergeMaps(List<Map<String, Values>> maps) {
return maps.stream()
.flatMap(m -> m.entrySet().stream())
.collect(Collectors.toMap(Map.Entry::getKey,
Map.Entry::getValue,
(v1,v2) -> new Values(v1,v2)));
}
假设您有一个Values
构造函数,它接受两个Values
实例并创建一个具有值的总和的实例。
当然,您可以在没有该构造函数的情况下编写合并函数。 例如:
(v1,v2) -> new Values(v1.getCount()+v2.getCount(),v1.getValue()+v2.getValue())
使用groupingBy的另一个解决方案:
Map<String, Optional<Values>> collect = list.stream()
.flatMap(map -> map.entrySet().stream())
.collect(groupingBy(Map.Entry::getKey, mapping(Map.Entry::getValue,
reducing((v1, v2) -> new Values(v1.count + v2.count, v1.values + v2.values)))));
注意:此映射的值为Optional<Values>
。 如果您的某个源映射上有null
值,例如map2.put("ddd", null);
它允许避免NullPointerException
并返回Optional.empty
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.