hom*_*son 15 java lambda java-8 java-stream
我有一个看起来像这样的地图列表:
[
{
"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
}
]
Run Code Online (Sandbox Code Playgroud)
我希望输出看起来像这样:
{
"A": {
"old": 1,
"new": 1
},
"B": {
"old": 1,
"new": 0.95
}
}
Run Code Online (Sandbox Code Playgroud)
...其中每个相关条目的值old和new的总和.
映射列表的数据类型是List<Map<String, Object>>,因此输出应该是a Map<String, Map<String, Double>>.
通过一些图表绘图,文档阅读和反复试验,我能够想出这个:
data.stream()
.collect(
Collectors.groupingBy(entry -> entry.get("name"),
Collectors.summingDouble(entry ->
Double.parseDouble(entry.get("old").toString())))
);
Run Code Online (Sandbox Code Playgroud)
生成类型的对象Map<String, Double>,其中输出是
{
"A": 1,
"B": 1
}
Run Code Online (Sandbox Code Playgroud)
对于old值的总结.但是,我无法将其转换为地图地图.像这样的东西:
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())
)
)
)
)
);
Run Code Online (Sandbox Code Playgroud)
不起作用,因为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);
});
Run Code Online (Sandbox Code Playgroud)
Map<String, Map<String, Double>> collect = data.stream().collect(
Collectors.groupingBy(m -> (String)m.get("name"),
Collector.of(LinkedHashMap::new,
(acc, e) -> Stream.of("old", "new").forEach(key -> acc.merge(key, (Double) e.get(key), Double::sum)),
(m1, m2) -> {
m2.forEach((k, v) -> m1.merge(k, v, Double::sum));
return m1;
})
));
Run Code Online (Sandbox Code Playgroud)
还有> Java 8方式:
Map<String, Map<String, Double>> stats = data.stream().collect(
Collectors.groupingBy(m -> (String) m.get("name"),
Collectors.flatMapping(m -> m.entrySet().stream().filter(e -> !"name".equals(e.getKey())),
Collectors.toMap(Map.Entry::getKey, e -> (Double)e.getValue(), Double::sum, LinkedHashMap::new)
)
));
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
549 次 |
| 最近记录: |