How to iterate over nested loop links to parent elements using Java 8 threads?

I want to iterate over nested lists using java8 streams and extract some results from lists on the first match. Unfortunately, I also need to get the values ​​from the parent content if the child matches the filter.

How can i do this?

// java7

 Result result = new Result(); //find first match and pupulate the result object. for (FirstNode first : response.getFirstNodes()) { for (SndNode snd : first.getSndNodes()) { if (snd.isValid()) { result.setKey(first.getKey()); result.setContent(snd.getContent()); return; } } } 

// java8

  response.getFirstNodes().stream() .flatMap(first -> first.getSndNodes()) .filter(snd -> snd.isValid()) .findFirst() .ifPresent(???); //cannot access snd.getContent() here 
+5
source share
2 answers

If you need both values ​​and you want to use flatMap (as required when you want to perform a short circuit operation, for example findFirst ), you need to map an object containing both values

 response.getFirstNodes().stream() .flatMap(first->first.getSndNodes().stream() .map(snd->new AbstractMap.SimpleImmutableEntry<>(first, snd))) .filter(e->e.getValue().isValid()) .findFirst().ifPresent(e-> { result.setKey(e.getKey().getKey()); result.setContent(e.getValue().getContent()); }); 

To use only the standard classes, I use the Map.Entry type as a pair, while the actual type of the pair may look more concise.

In this particular use case, you can move the filter operation to the internal thread

 response.getFirstNodes().stream() .flatMap(first->first.getSndNodes().stream() .filter(snd->snd.isValid()) .map(snd->new AbstractMap.SimpleImmutableEntry<>(first, snd))) .findFirst().ifPresent(e-> { result.setKey(e.getKey().getKey()); result.setContent(e.getValue().getContent()); }); 

which has a neat effect for only one matching element, an instance of Map.Entry will be created (well, as the current implementation is not as lazy as it should , but even then it will create smaller objects than in the first version).

+10
source

It should be like this:

Edit: Thanks Holger for pointing out that the code won't stop when the first valid FirstNode is valid

 response.getFirstNodes().stream() .filter(it -> {it.getSndNodes().stream().filter(SndNode::isValid).findFirst(); return true;}) .findFirst() .ifPresent(first -> first.getSndNodes().stream().filter(SndNode::isValid).findFirst().ifPresent(snd -> { result.setKey(first.getKey()); result.setContent(snd.getContent()); })); 

The test can be found here.

-1
source

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


All Articles