背景
我有一个看起来像这样的 map 列表:
[
{
"name": "A",
"old": 0.25,
"new": 0.3
},
{
"name": "B",
"old": 0.3,
"new": 0.35
},
{
"name": "A",
"old": 0.75,
"new": 0.7
},
{
"name": "B",
"old": 0.7,
"new": 0.60
}
]
我希望输出看起来像这样:
{
"A": {
"old": 1,
"new": 1
},
"B": {
"old": 1,
"new": 0.95
}
}
...其中 old
的值和 new
对每个相关条目求和。
map 列表的数据类型是List<Map<String, Object>>
, 所以输出应该是 Map<String, Map<String, Double>>
.
我尝试过的
通过一些图表绘制、文档阅读以及反复试验,我得出了这个结论:
data.stream()
.collect(
Collectors.groupingBy(entry -> entry.get("name"),
Collectors.summingDouble(entry ->
Double.parseDouble(entry.get("old").toString())))
);
生成类型为 Map<String, Double>
的对象,其中输出是
{
"A": 1,
"B": 1
}
对于 old
的总结值。但是,我不能完全将其转换为 map 的 map 。像这样:
data.stream()
.collect(
Collectors.groupingBy(entry -> entry.get("name"),
Collectors.mapping(
Collectors.groupingBy(entry -> entry.get("old"),
Collectors.summingDouble(entry ->
Double.parseDouble(entry.get("old").toString())
)
),
Collectors.groupingBy(entry -> entry.get("new"),
Collectors.summingDouble(entry ->
Double.parseDouble(entry.get("new").toString())
)
)
)
)
);
不起作用,因为 Collectors.mapping()
只需要一个映射函数和一个下游收集器,但我不确定如何一次映射两个值。
我需要另一个函数来创建两个不同值的映射吗?我们也非常感谢任何关于更好的方法的建议。
最佳答案
可以使用流,也可以使用Map
的computeIfAbsent
和merge
方法:
Map<String, Map<String, Double>> result = new LinkedHashMap<>();
data.forEach(entry -> {
String name = (String) entry.get("name");
Map<String, Double> map = result.computeIfAbsent(name, k -> new HashMap<>());
map.merge("old", (Double) entry.get("old"), Double::sum);
map.merge("new", (Double) entry.get("new"), Double::sum);
});
关于java - 如何使用 Java 8 streaming api 从 map 列表创建 map map ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52651635/