Java 8 nested streams: return value on last stream

This question can be thought of as based on java 8 nested streams

Suppose I have Batch

with Basket

with Item

:

public class Batch {
    private List<Basket> baskets;
}

public class Basket {
    private List<Item> items; 
}

public class Item {
    private String property;
    private int value;
}

      

I would like to rewrite this method with Java 8 streams.

public class SomeService {
    public int findValueInBatch(Batch batch) {
        for (Basket basket : batch.getBaskets()) {
            for (Item item : basket.getItems()) {
                if (item.getProperty().equals("someValue") {
                    return item.getValue();
                }
            }
        }
        return 0;
    }
}

      

How should I do it?

First step to where I want to go:

public int findValueInBatch(Batch batch) {
    for (Basket basket : batch.getBaskets()) {
        basket.getItems().stream()
            .filter(item -> item.getProperty.equals("someValue") 
            .findFirst()
            .get();
            // there I should 'break'
    }
}

      

Many thanks.

+5


source to share


3 answers


baskets.stream()
            .flatMap(basket -> basket.getItems().stream())
            .filter(item -> item.equals("someValue"))
            .findAny()
            .orElseThrow(NoSuchElementException::new);

      



The advantage of using findAny

instead findFirst

is that it findFirst

doesn't work with parallel threads. Therefore, if you want to parallelize the above operation, you will need to replace the method stream()

withparallel()

+5


source


  1. Use flatMap

    to get a list of nested lists, extract each one List<Item>

    and concatenate them into Stream<Item>

    , it acts as if all sub-streams were concatenated together.
  2. Use filter

    to ignore irrelevant items.
  3. Use findFirst

    to get only the first case and stop processing
  4. Use orElseThrow

    to throw an exception if someValue was not found .

Here you are,



public class SomeService {
    public int findValueInBatch(Batch batch) {
        return batch.getBaskets().stream()
            .flatMap(basket -> basket.getItems().stream())
            .filter(item -> item.getProperty.equals("someValue"))
            .findFirst()
            .orElseThrow(() -> new IllegalArgumentException("value not found"));
    }
}

      

+4


source


To eliminate both loops, you can use flatMap

to create Stream<Item>

all Item

all Basket

:

return batch.getBaskets()
            .stream()
            .flatMap(b -> b.getItems().stream())
            .filter(item -> item.getProperty.equals("someValue"))
            .findFirst()
            .orElse(some default value); // using .get() would throw an exception
                                         // if no match is found

      

+3


source







All Articles