【问题标题】:Java 8 lambda adding to a list in a Hashmap, in a HashmapJava 8 lambda 添加到 Hashmap 中的列表中,在 Hashmap 中
【发布时间】:2016-03-08 16:17:50
【问题描述】:

我有一个List<POJO>,我想从中提取数据,我感兴趣的变量是:

  • Environment: String
  • Application: String
  • Throughput: Double

有7个Environment对象,每个Environment有18个Application对象,每个对象有多个values

我正在尝试遍历 List<POJO> 并将这些值存储在 Hashmap<Environment.ToString, Hashmap<Applications.ToString, List<Double>>

我正在尝试使用 Java 8 的 Lambda 功能;到目前为止我的代码:

private HashMap<String, List<BigDecimal>> appMap = new HashMap<String, List<BigDecimal>>();
private HashMap<String, HashMap> envMap = new HashMap<String, HashMap>();

for(POJO chartModel: List<POJO>) {
    appMap.computeIfAbsent(chartModel.getName(), v -> new ArrayList<BigDecimal>())
          .add(BigDecimal.valueOf(chartModel.getThroughput()));
    envMap.put(chartModel.getEnvironment(), appMap);
}

首先,是否有一种速记方法可以使用Java8 迭代内部Map 内的List

其次,我的代码不太正确,因此当前映射将所有 Throughput 值添加到其 Application 键中,因此我最终得到了 18 个键和值列表。

我需要它做的是在我的envMap 中我应该有7 个Environment 对象,每个对象都有18 个Application 对象和值,所以总共有126 个Application 对象。这可以按照我尝试的方式实现吗,有 Lambda 方法可以实现吗?

【问题讨论】:

  • 好吧,对于初学者来说,你只有一个appMap 的实例,这将被插入envMap 7 次,每个Environment 一次。

标签: java lambda hashmap java-8


【解决方案1】:

您需要使用2个分组操作:第一个根据环境分组,第二个根据名称分组。最后,您需要将每个值映射到其吞吐量的BigDecimal 值。

假设pojoList&lt;POJO&gt;

Map<String, Map<String, List<BigDecimal>>> result =
    pojo.stream()
        .collect(Collectors.groupingBy(
            POJO::getEnvironment,
            Collectors.groupingBy(
                POJO::getName,
                Collectors.mapping(p -> BigDecimal.valueOf(p.getThroughput()), Collectors.toList())
            )
        ));

【讨论】:

    【解决方案2】:

    您只创建了一个MapappMap,您将每个键都放入envMap。您显然想为每个不同的键创建一个新的Map,并且您已经知道正确的工具computeIfAbsent。但你也应该注意“diamond operator”。虽然不是 Java 8 的新功能,但您的代码显然会从删除类型参数的重复中受益。综上所述,操作如下所示:

    HashMap<String, Map<String, List<BigDecimal>>> envMap = new HashMap<>();
    for(POJO chartModel: list) {
        envMap.computeIfAbsent(chartModel.getEnvironment(), env -> new HashMap<>())
            .computeIfAbsent(chartModel.getName(), name -> new ArrayList<>())
            .add(BigDecimal.valueOf(chartModel.getThroughput()));
    }
    

    您也可以使用 Stream API as shown by Tunaki 表达相同的逻辑,但您不需要这样做。

    【讨论】:

    • 使用一种方法比另一种方法有什么优势吗?
    • 在这种特定情况下,没有重要的区别。您可以使用任何您喜欢的方式,但值得了解两种方式
    • 我实际上更喜欢这个解决方案,因为这里我们的嵌套调用较少。连续五个右括号太多了。
    猜你喜欢
    • 2021-08-01
    • 2021-10-10
    • 1970-01-01
    • 1970-01-01
    • 2016-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-20
    相关资源
    最近更新 更多