如何使用Java 8 Streams和Lambdas迭代嵌套for循环引用父元素?

时间:2017-02-03 20:14:26

标签: lambda java-8 java-stream

我有下面的代码。

public static ModuleKey getDeployableModuleFromModulesList(List<Module> modules) {
        ModuleKey deployableModuleKey = null;
        for(Module module : modules) {
            List<Artifact> artifacts = module.getArtifacts();
            for(Artifact artifact : artifacts) {
                if(artifact.getType().equals("ear")) {
                    return module.getKey();
                } else if(!artifact.getType().equals("ear")) {
                    if(artifact.getType().equals("war")) {
                        deployableModuleKey = module.getKey();
                    } 
                }
            }
        }
        return deployableModuleKey;
    }

此代码使用key ='war'找到第一个'deployableModuleKey'或使用key ='war'找到最后一个'deployableModuleKey'。 我想使用Java 8 Streams和Lambdas实现与上面相同的功能。

到目前为止,我所尝试的是:

modules.stream().flatMap(e -> e.getArtifacts().stream())
  .filter(e -> e.getType().equals("ear")).findFirst()
  .orElseGet(() -> modules.stream().flatMap(e -> e.getArtifacts().stream())
  .filter(e -> e.getType().equals("war")).reduce((a, b) -> b).orElse(null));

上面的代码段将返回Artifact类型的对象,而不是Module。我想获得工件与条件匹配的模块。找到模块后,我可以通过module.getKey()返回密钥。 为此,我想知道我们如何引用父元素的循环。

我不确定我的Java 8代码是否完全正确 在这方面有人可以帮助我吗?

3 个答案:

答案 0 :(得分:0)

使用流的东西是,一旦使用filtermap等中间操作修改了流,就无法返回上一个操作中的值。因此,您必须找到变通方法,以便始终保留(在您的情况下为Module)您要在流中引用的值。在以下解决方案中,我使用anyMatch操作打开两个辅助流,如果模块包含包含所需密钥的工件,则会给出正值。

这应该可以解决问题:

ModuleKey key = Optional.ofNullable(modules.stream().filter(m -> m.getArtifacts().stream()
    .anyMatch(a -> a.equals("ear"))).findFirst().orElse(modules.stream()
    .filter(m -> m.getArtifacts().stream().anyMatch(a -> a.equals("war")))
    .reduce((a, b) -> b).orElse(null))).map(Module::getKey).orElse(null);

要查找第一个元素,请使用findFirst,它会返回Optional<T>。我们将OptionalOptional#orElse链接起来,将其展开,如果它为空,则返回另一个值(在这种情况下使用reduce((a, b) -> b)来查找最后一个元素)。如果没有找到任何内容,我们不希望代码抛出NullPointerException。因此,在我们调用getKey方法之前,我们将所有这些内容包装到Optional Optional.ofNullable并将orElse设置为null,这是您指定的默认值代码。

作为旁注,

else if(!artifact.getType().equals("ear")) {
    if(artifact.getType().equals("war")) {
    }
}

可以缩减为

else if(artifact.getType.equals("war")) {
}

答案 1 :(得分:0)

我认为你知道多余的5.248e+05检查旧的Java样式代码。

我已经编写了大量的单一操作流程,分解为任何人都能理解的小型易操作函数。

 // Set the arguments of the kernel
  clSetKernelArg(kernel, 0, sizeof(cl_mem), (void *)&inputBuffer);
  clSetKernelArg(kernel, 1, local_item_size*sizeof(double), NULL);
  clSetKernelArg(kernel, 2, nWorkGroups*sizeof(double), NULL);
  clSetKernelArg(kernel, 3, sizeof(cl_mem), (void *)&finalSumBuffer);

答案 2 :(得分:0)

我已经找到解决问题的方法。

public static ModuleKey getDeployableModuleFromModulesList(List<Module> modules) {
    Optional<ModuleKey> op = modules.stream().filter(module -> module.getArtifacts().stream().anyMatch(artifact -> artifact.getType().equals("ear"))).map(module -> module.getKey()).findFirst();
    if (!op.isPresent()) {
        op = modules.stream().filter(module -> module.getArtifacts().stream().anyMatch(artifact -> artifact.getType().equals("war"))).map(module -> module.getKey()).reduce((a, b) -> b);
    }
    return op.orElse(null);
}

无论如何,也欢迎其他解决方案。如果有人添加了另一个解决方案,我会尝试所有这些解决方案。