Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java 8 eagerly get the result of an intermediate stream operation

Given the following code:

List<String> list = Arrays.asList("a", "b", "c");
        list.stream()
        .map(s -> s + "-" + s)                 //"a-a", "b-b", "c-c"
        .filter(s -> !s.equals("b-b"))         //"a-a", "c-c"
        .forEach(s -> System.out.println(s));

map and filter are intermediate operations and forEach is a terminal operation. Only after the execution of the terminal operation we can have the result of the data transformation.

Is there any way to force the evaluation to be more eager and to have some kind of intermediate result - without breaking the stream operations chain? For example I want to have the list of "a-a", "b-b", "c-c" (which would be the result of the first intermediate operation).

like image 847
Anton Avatar asked May 14 '15 07:05

Anton


People also ask

Which stream operations are eagerly loaded in Java?

Terminal operations are eagerly loaded. They don't produce end result. They produce end result.

What is intermediate operation Java 8?

Intermediate Operation- These operations are used to pipeline other methods and to transform into the other streams. They don't produce results because these operation does not invoke until the terminal operation gets executed. Below are the examples − sorted(Comparator<T>) peek(Consumer<T>)

Why intermediate operations are lazy in Java 8?

Streams are lazy because intermediate operations are not evaluated until terminal operation is invoked. Each intermediate operation creates a new stream, stores the provided operation/function and return the new stream. The pipeline accumulates these newly created streams.

What is intermediate operation in stream Java?

Stream. Intermediate operators do not execute until a terminal operation is invoked, i.e. they are not executed until a result of processing is actually needed. We will be discussing a few of the important and most frequently used: filter(predicate) Method.


2 Answers

You can use peek:

List<String> allPairs = new ArrayList<>();
List<String> list = Arrays.asList("a", "b", "c");
    list.stream()
    .map(s -> s + "-" + s)                 //"a-a", "b-b", "c-c"
    .peek(allPairs::add)
    .filter(s -> !s.equals("b-b"))         //"a-a", "c-c"
    .forEach(s -> System.out.println(s));

This way the computation still won't start until the terminal operation, but you can "intercept" the stream content at any point and use it in any way you like.

Beware however if your terminal operation is short-circuiting (like findFirst): this way not all the elements might be passed to peek.

like image 99
Tagir Valeev Avatar answered Oct 20 '22 06:10

Tagir Valeev


Well ... if I understand your question correctly, you have to apply a terminal operation, before filtering by the not equals "b-b" predicate. Then, you should call .stream() on the intermediate result and do the filtering:

List<String> list = Arrays.asList("a", "b", "c");
list.stream()
    .map(s -> s + "-" + s)           //"a-a", "b-b", "c-c"
    .collect(Collectors.toList())    //intermediate result
    .stream()
    .filter(s -> !s.equals("b-b"))   //"a-a", "c-c"
    .forEach(s -> System.out.println(s));
like image 39
Konstantin Yovkov Avatar answered Oct 20 '22 07:10

Konstantin Yovkov