java - 优化这些用于在 Java 8 中创建 HashMap 的嵌套 for 循环的最佳方法是什么?

标签 java lambda java-8 java-stream nested-loops

在我开始之前,我已经对此进行了大量研究,但尚未找到解决方案。我已经引用了以下主题以及许多其他主题,但我只是想证明我在提问之前已经长期努力地寻找解决方案。我的情况比这些更复杂:

How to convert nested for loop into Hashmap using java stream

How to iterate nested lists with lambda streams?

What is the proper way of replacing a nested for loop with streams in Java 8?

好的,所以我正在构建一个服务,该服务使用另一个提供我无法控制的类的服务。我必须在类出现时使用它,因为它是每次项目构建时从文件动态生成的。大量的嵌套类和嵌套列表完全是一团糟。命名约定也很乱,但为了便于阅读,我在这里清理了很多。我需要深入研究列表以从一个对象 (Lower) 中获取两个值(code 和 cgyCode),并使用一个作为键(code)和一个作为值(cgyCode)创建一个 hashmap。

我有这样工作的FUNCTIONING逻辑:

//Code passing in object Rpn rpn which contains the nested lists        

HashMap<String, String> codeMap = new HashMap<String, String>();

            for (Object datDtl : rpn.getDatDtlOrRpnDtl()) {

                if (datDtl instanceof Rpn.DatDtl) {

                    for (Rpn.DatDtl.Upper upper : ((Rpn.DatDtl) datDtl).Upper()) {

                        for (Rpn.DatDtl.Upper.Lower lower : Upper.getLower()) {

                            codeMap.put(lower.getCode(), lower.getCgyCode());
                        }
                    }
                }
            }

所以我尝试了很多变体来将整个事情变成一个 lambda 流,如果这是正确的做法的话。我一直无法让整个事情正常进行,总有一些事情搞砸了。所以我最好的办法是流式传输最后一个循环,但上面没有。我觉得它可以合并的方式不止于此。

功能:

HashMap<String, String> codeMap = new HashMap<String, String>();
                for (Object datDtl : rpn.getDatDtlOrRpnDtl()) {

                    if (datDtl instanceof Rpn.DatDtl) {

                        for (Rpn.DatDtl.Upper upper : ((Rpn.DatDtl) datDtl).Upper()){

                             upper.getLower().stream().forEach(lower -> codeMap.put(lower.getCode(), lower.getCgyCode()));

              }
         }
    }

我已经尝试了很多过滤、平面 map 和流的组合,但是我没有成功地将所有功能转换为一系列 lambda 语句,我也不知道这是否是最好的行动方案。

所以我的问题是:在性能方面优化此代码的最佳方法是什么,如果不是所有代码都可以使用 lambda 和流进行优化,从学习的角度来看,为什么不呢?


下面我将演示一些我尝试过的其他事情,这些事情很接近,但最终我无法解决映射问题。

失败 1:

HashMap<String, String> codeMap = new HashMap<>();
rpn.getDatDtlOrRpnDtl().stream()
                    .filter(datDtl -> datDtl instanceof Rpn.DatDtl)
                    .flatMap(datDtl -> ((Rpn.DatDtl)datDtl).getUpper().stream()
                    .flatMap(upper -> upper.getLower().stream()
                    .forEach(lower -> codeMap.put(lower.getCode(), lower.getCgyCode()))));

除了 .forEach 函数给出错误“不存在类型变量 R 的实例,因此 void 符合 Stream”之外,上面的代码似乎可以正常工作。这与在包含 lambda 的功能循环中工作的逻辑相同,所以这让我觉得我到达“较低”的方式是不正确的。

失败 2:

HashMap<String, String> codeMap = rpn.getDatDtlOrRpnDtl().stream()
                    .filter(datDtl -> datDtl instanceof Rpn.DatDtl)
                    .flatMap(datDtl -> ((Rpn.DatDtl)datDtl).getUpper().stream()
                    .flatMap(upper -> upper.getLower().stream()
                    .collect(Collectors.toMap(lower -> lower.getCode(), lower -> lower.getCgyCode())));

此代码与上面的代码类似。这里的错误是“.getCode()”和“.getCgyCode()”不被识别为有效方法,即使它们是在 Lower 类中定义的。这进一步表明我的理论是正确的,我到达“降低”的方式并不是正确的方式。

我已经尝试过许多其他的 .filter、.map 等变体。但我在这里完全不知所措。可能无法完成我想做的事情,但如果是这样,我想知道为什么以及下一个最好的事情是什么。

感谢所有读到这里并想和我一起解决这个问题的人。


编辑:

解决方案让我找到了答案,但为了记录其他可能遇到此问题的人,我将格式化最终有效的解决方案:

Map<String, String> codeMap = rpn.getDatDtlOrRpnDtl().stream()
                    .filter(datDtl -> datDtl instanceof Rpn.DatDtl)
                    .flatMap(datDtl -> ((Rpn.DatDtl) datDtl).Upper().stream())
                    .flatMap(upper -> upper.getLower().stream())
                    .forEach(lower -> codeMap.put(lower.getCode(), lower.getCgyCode());

最佳答案

您的两次尝试都非常接近。

您的代码没有缩进以显示它,但是您在失败尝试中的 collect 调用之后放置了一些右括号。

这不是流操作的正确顺序。 最后 操作应该是对collect 的调用。如所写,您的代码将生成一个 Stream 作为其结果,而不是一个 Map

试试下面的代码:

Map<String, String> codeMap = Rpn.getDatDtlOrRpnDtl().stream()
                    .filter(datDtl -> datDtl instanceof Rpn.DatDtl)
                    .flatMap(datDtl -> ((Rpn.DatDtl) datDtl).Upper().stream())
                    .flatMap(upper -> upper.getLower().stream())
                    .collect(Collectors.toMap(lower -> lower.getCode(), lower -> lower.getCgyCode());

关于java - 优化这些用于在 Java 8 中创建 HashMap 的嵌套 for 循环的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48589552/

相关文章:

java - 将 apache netbeans gradle 项目导出到 jar 文件

Java - 删除引号字符串外逗号周围的空格?

java - 修剪文件名足够短

kotlin - 如何注解lambda的返回值

c# - C# 捕获外部变量中的 Lambdas - 请解释书中的示例 "C# in nutshell 5.0"

java - 旧的 AppFuse ...什么框架是直接迁移?

c++ - find_if 中具有多个参数的 Lambda

FilenameFilter 的 java 8 lambda 表达式

Java8 LocalDate 解析异常

java - 我如何将大数字转换为 ZonedDateTime java 字段