如何使用Java8流和Lambdas迭代引用父元素的嵌套for循环?
我有下面的代码如何使用Java8流和Lambdas迭代引用父元素的嵌套for循环?,lambda,java-8,java-stream,Lambda,Java 8,Java Stream,我有下面的代码 public static ModuleKey getDeployableModuleFromModulesList(List<Module> modules) { ModuleKey deployableModuleKey = null; for(Module module : modules) { List<Artifact> artifacts = module.getArtifacts();
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;
}
上面的代码片段将返回类型为工件
的对象,而不是模块
。我想获得工件符合条件的模块。找到模块后,我可以通过执行module.getKey()
返回密钥。
为此,我想知道如何引用循环的父元素
我不确定我的Java 8代码是否完全正确。有人能在这方面帮助我吗?流的问题是,一旦您使用中间操作(如
filter
或map
)修改了流,您就不能引用上一个操作的值。因此,您必须找到解决方法,以便始终保持(在您的情况下,模块
)您希望在流中引用的值。在下面的解决方案中,我使用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
链接到Optional#orElse
,它将打开它,如果它为空,则返回另一个值(在本例中,使用reduce((a,b)->b)
查找最后一个元素)。如果没有找到任何内容,我们不希望代码抛出NullPointerException
。因此,在调用getKey
方法之前,我们使用Optional.ofNullable
将所有这些内容包装成一个Optional
,并将orElse
设置为null
,这是代码中指定的默认值
作为旁注
else if(!artifact.getType().equals("ear")) {
if(artifact.getType().equals("war")) {
}
}
可以简化为
else if(artifact.getType.equals("war")) {
}
我想您已经意识到冗余的if
检查您的旧Java风格代码
我已经通过分解成每个人都能理解的较小的简单函数,编写了您的大型单一操作流
public static ModuleKey getDeployableModuleFromModulesList(List<Module> modules) {
return findEARKey(modules.stream())
.orElse(findWARKey(modules.stream()).orElse(null));
}
public static Optional<ModuleKey> findEARKey(Stream<Module> moduleStream){
return moduleStream.flatMap(e -> e.getArtifacts().stream())
.filter(e -> e.getType().equals("ear"))
.map(Artifact::getKey).findFirst();
}
public static Optional<ModuleKey> findWARKey(Stream<Module> moduleStream){
return moduleStream.flatMap(e -> e.getArtifacts().stream())
.filter(e -> e.getType().equals("war"))
.map(Artifact::getKey).findFirst();
}
公共静态模块key getDeployableModuleFrommoduleList(列出模块){
返回findEARKey(modules.stream())
.orElse(findWARKey(modules.stream()).orElse(null));
}
公共静态可选findEARKey(流模块Stream){
返回moduleStream.flatMap(e->e.getArtifacts().stream())
.filter(e->e.getType().equals(“ear”))
.map(工件::getKey).findFirst();
}
公共静态可选密钥(流模块Stream){
返回moduleStream.flatMap(e->e.getArtifacts().stream())
.filter(e->e.getType().equals(“war”))
.map(工件::getKey).findFirst();
}
我已经想出了解决问题的办法
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);
}
公共静态模块key getDeployableModuleFrommoduleList(列出模块){
可选op=modules.stream().filter(module->module.getArtifacts().stream().anyMatch(artifact->artifact.getType().equals(“ear”)).map(module->module.getKey()).findFirst();
如果(!op.isPresent()){
op=modules.stream().filter(module->module.getArtifacts().stream().anyMatch(artifact->artifact.getType().equals(“war”)).map(module->module.getKey()).reduce((a,b)->b);
}
返回op.orElse(空);
}
无论如何,也欢迎其他解决方案。如果有人添加了其他解决方案,我将尝试所有解决方案。我建议您将此过程分解为几个函数。这并不意味着不鼓励Java8流链接操作,而是尽可能使它们清晰和原子化。我怀疑使用流比实际代码更好。流不适合在中间操作之间保持状态。另外,您当前的代码对所有工件进行一次遍历,而建议的解决方案进行两次遍历。如果您只想通过一次就可以完成此操作,我建议您创建自己的收集器(这里有很多关于创建收集器的问题,只需选择一个并从那里继续)如果使用您的代码段,我会遇到以下编译错误类型列表的方法筛选器((m)->{})未定义,类型ModuleUtil的方法getKey()未定义。getKey()
方法是模块
对象的一部分。@RITZXAVI我用记事本++而不是普通的IDE原型化了我的代码,出现了新的问题。我编辑了我的答案来修复它们,告诉我你是否仍然遇到问题。现在我得到了这个错误可选类型中的方法orElse(模块)不适用于参数(可选)
@RITZXAVI-Phew!最后在我的IDE中编辑了它,应该可以了。错误是我正在输入orElse
,它需要一个模块
,返回值为findFirst
,这是一个可选的
。我只是用另一个orElse
打开了最后一个Optional
。再说一次,如果你仍然有问题,请告诉我。虽然它在语法上是正确的,但在功能上,它并没有达到我的预期。不管怎样,我已经想出了解决办法,我将发布。你可以查一下。谢谢您的尝试。如果我想要类型为'ear'或'war'的'deployableModuleKey',我认为您的代码很好。但是,我想要的是第一个类型为'ear'的'deployableModuleKey'。如果ear
不存在,那么我想返回最后一个moduleKey,类型为'war'。此外,此代码返回工件键而不是模块键yes,在工件
对象中没有名为key
的属性。
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);
}