java - 如何使用 Java 8 streaming api 从 map 列表创建 map map

标签 java lambda java-8 java-stream

背景

我有一个看起来像这样的 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()只需要一个映射函数和一个下游收集器,但我不确定如何一次映射两个值。

我需要另一个函数来创建两个不同值的映射吗?我们也非常感谢任何关于更好的方法的建议。

最佳答案

可以使用流,也可以使用MapcomputeIfAbsentmerge方法:

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/

相关文章:

java - Google Drive API 不下载文件 (Java v3)

lambda - Terraform:为调用 Lambda 的 AWS API Gateway 创建 url 路径参数?

Java 8 - 如何将元素合并到 HashMap

java - 在 Java 8 中的 Map<String, List> 中向 List 添加值

java - 将java bean写入Csv表格式

java - 无法编辑表格单元格: Java Swing

javascript - 为什么使用 lambda 的 String.replace() 比重复调用 RegExp.exec() 的 while 循环慢?

java - 重新解析和映射列表中的元素

`(a,b) -> a+b` 的 Java8 函数类型

java - 推迟消息的最佳方式是什么?