Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java 8 Stream - Filter and foreach method not printing as expected

I am executing the following program:

Stream.of("d2", "a2", "b1", "b3", "c")
.filter(s -> {
    System.out.println("filter: " + s);
    return true;
})
.forEach(s -> System.out.println("forEach: " + s));

And the output I got is:

filter:  d2
forEach: d2
filter:  a2
forEach: a2
filter:  b1
forEach: b1
filter:  b3
forEach: b3
filter:  c
forEach: c

However, I was expecting the following output:

filter:  d2
filter:  a2
filter:  b1
filter:  b3
filter:  c 
forEach: d2
forEach: a2
forEach: b1
forEach: b3
forEach: c

Meaning, first the filter method loop should have executed completely and then the forEach method loop should have started.

Is there anything I am doing wrong?

like image 642
KayV Avatar asked Nov 29 '16 10:11

KayV


1 Answers

Your expectation is wrong.

When the terminal operation forEach is executed, it consumes one element of the Stream at a time. Each element it consumes has to pass all the intermediate operations of the Stream, which causes filter to be executed on the element just prior to forEach being executed on same element (assuming the element passes the filter).

In other words, filter is lazily applied to each element just when the next operation in the Stream pipeline requires its next element (in your case the next operation is forEach).

This means that if your terminal operation would only require some of the Stream elements to be processed (for example, if you replaced forEach() with findFirst()), the filter() operation would only be executed until the first element passes it (which in your example means the filter will be executed only for the first element).

like image 86
Eran Avatar answered Oct 18 '22 22:10

Eran