How to iterate over nested loops on parent elements using Java 8 Streams and Lambdas?

I have the code below.

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; } 

This code finds the first "deployableModuleKey" with key = "ear" or the last with key = "war". I want to achieve the same features as above using Java 8 Streams and Lambdas.

So far I have tried:

 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)); 

The code snippet above returns an object of type Artifact instead of Module . I want to get the module where the artifact meets the conditions. Once I find the module, I can return the key by doing module.getKey() . For this, I would like to know how we refer to the parent elements for the loop.

I'm not sure my Java 8 code is absolutely right.
Can anyone help me in this regard?

+5
source share
3 answers

I figured out a solution to my problem.

 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); } 

In any case, other solutions are also welcome. If someone adds another solution, I will try everything.

0
source

Thing with streams, once you change your stream using an intermediate operation such as filter or map , you cannot return to the values ​​from the previous operation. Therefore, you need to find workarounds to always (in your case, Module ) store the value that you want to use in your stream. In the following solution, I open two secondary streams using anyMatch operations, which give a positive value if the module contains an artifact containing the required key.

This should do the trick:

 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); 

To find the first item, use findFirst , which returns Optional<T> . We associate this Optional with Optional#orElse , which expands it and, if empty, returns a different value (in this case, use reduce((a, b) -> b) to find the last element). If nothing is found, we do not want the code to NullPointerException . Therefore, before we call the getKey method, we will complete all this in Optional with Optional.ofNullable and set orElse to null to the default value specified in your code.

As a side note,

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

can be reduced to

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

I think you know that redundant if checks your old Java style code.

I wrote my long workflow, breaking it up into smaller, frivolous functions that everyone could understand.

 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(); } 
0
source

Source: https://habr.com/ru/post/1263802/


All Articles