首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何使用Java 8流api从地图列表创建地图

如何使用Java 8流api从地图列表创建地图
EN

Stack Overflow用户
提问于 2018-10-05 00:35:34
回答 3查看 1.7K关注 0票数 15

背景

我有一个地图列表,如下所示:

代码语言:javascript
复制
[
  {
    "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
  }
]

我希望输出是这样的:

代码语言:javascript
复制
{
  "A": {
    "old": 1,
    "new": 1
  },
  "B": {
    "old": 1,
    "new": 0.95
  }
}

对于每个相关条目,将对oldnew的值求和。

映射列表的数据类型是List<Map<String, Object>>,因此输出应该是Map<String, Map<String, Double>>

我尝试过的

通过一些图表绘制、文档阅读和反复试验,我能够得出以下结论:

代码语言:javascript
复制
data.stream()
    .collect(
        Collectors.groupingBy(entry -> entry.get("name"),
            Collectors.summingDouble(entry ->
                Double.parseDouble(entry.get("old").toString())))
    );

生成Map<String, Double>类型的对象,其中输出为

代码语言:javascript
复制
{
  "A": 1,
  "B": 1
}

获取old值的总和。但是,我不能完全将其转换为地图。如下所示:

代码语言:javascript
复制
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()只接受一个映射函数和一个下游收集器,但我不确定如何同时映射两个值。

是否有其他函数需要创建两个不同值的映射?任何关于更好的方法的建议也是非常感谢的。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-10-05 01:29:33

您可以使用streams,但也可以使用MapcomputeIfAbsentmerge方法:

代码语言:javascript
复制
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);
});
票数 9
EN

Stack Overflow用户

发布于 2018-10-05 01:18:05

您的第一次尝试已接近解决方案,但是您需要执行一些自定义代码才能完全完成图片。

您将需要实现您自己的collector,一个将多个map转换为一个double map。

这看起来像这样:

代码语言:javascript
复制
       Collector.of(
            () -> new HashMap<>(),
            (Map<String, Double>target, Map<String, Object> source) -> {
                target.merge("old", (Double)source.get("old"), Double::sum);
                target.merge("new", (Double)source.get("new"), Double::sum);
            },
            (Map<String, Double> map1, Map<String, Double> map2) -> {
                map2.forEach((k, v) -> map1.merge(k, v, Double::sum));
                return map1;
            }
        ) 

这与您的初始尝试分组相结合,解决了以下问题:

代码语言:javascript
复制
data.stream()
    .collect(
        Collectors.groupingBy(entry -> entry.get("name"),
            // Insert collector here
        )
    );

在线完整代码示例:http://tpcg.io/pJftrJ

票数 4
EN

Stack Overflow用户

发布于 2018-10-05 01:00:18

您可以声明一个名为Pair的类

代码语言:javascript
复制
public class Pair {
    private final double oldVal;
    private final double newVal;

    public Pair(double oldVal, double newVal) {
        super();
        this.oldVal = oldVal;
        this.newVal = newVal;
    }

    public double getOldVal() {
        return oldVal;
    }

    public double getNewVal() {
        return newVal;
    }

    @Override
    public String toString() {
        return "{oldVal=" + oldVal + ", newVal=" + newVal + "}";
    }

}

然后像这样做,

代码语言:javascript
复制
Map<Object, Pair> result = sourceMaps.stream()
        .collect(Collectors.toMap(m -> m.get("name"),
                m -> new Pair((double) m.get("old"), (double) m.get("new")),
                (p1, p2) -> new Pair(p1.getOldVal() + p2.getOldVal(), p1.getNewVal() + p2.getNewVal())));

这是输出结果,

代码语言:javascript
复制
{A={oldVal=1.0, newVal=1.0}, B={oldVal=1.0, newVal=0.95}}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52651635

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档