简体   繁体   中英

How does Lazy Evaluation and Eager Evaluation work in Java 8

I understand Streams are lazy until terminal method is called on the stream. What I know is that after terminal method is called all the intermediate methods are executed in order of their calling.

But with the following program I can't get my head around how stream is working. Here is the code, I have tried.

import java.util.*;
import java.util.stream.*;

class TestEagerLazy
{
    public static void main(String[] args) {
        ArrayList<Integer> a = new ArrayList<>();

        a.add(4);a.add(5);a.add(8);
        a.add(7);a.add(3);a.add(65);
        a.add(87);a.add(2);a.add(12);
        a.add(58);a.add(42);

        Stream<Integer> st = a.stream().filter(b->{System.out.println("Tested: " + b);return (b%2)==0;});

        Spliterator<Integer> it = st.spliterator();

        System.out.println("\n\nIterator Results:");
        while(it.tryAdvance((j)->System.out.println("iter: "+j)));


        System.out.println("Last Statement");


    }
}

The output I expected assuming tryAdvance on the stream's spliterator is as follows:

Iterator Results:
Tested: 4
Tested: 5
Tested: 8
Tested: 7
Tested: 3
Tested: 65
Tested: 87
Tested: 2
Tested: 12
Tested: 58
Tested: 42
iter: 4
iter: 8
iter: 2
iter: 12
iter: 58
iter: 42
Last Statement

But the output I got was as follows:

Iterator Results:
Tested: 4
iter: 4
Tested: 5
Tested: 8
iter: 8
Tested: 7
Tested: 3
Tested: 65
Tested: 87
Tested: 2
iter: 2
Tested: 12
iter: 12
Tested: 58
iter: 58
Tested: 42
iter: 42
Last Statement

What is the exact program flow? How does program flow from tryAdvance to filter on the stream and back.

Stateless streams are designed to handle a possibly infinite amount of elements. For this to be possible, the stream cannot attempt to evaluate each operation on all of the elements at once.

Sequential streams always execute the pipeline one element at a time. Each element goes through the entire pipeline before the next element starts. This is what allows lazy evaluation to be effective. It allows the stream to short-circuit, such as with findFirst or allMatch . If all of the elements were processed at once at each stage, streams would not be able to handle infinite data sources, such as from Stream.iterate .

The output of your code demonstrates that the elements go through the pipeline one at a time:

Iterator Results:
Tested: 4   // starting 1st element
iter: 4     // ending 1st element
Tested: 5   // starting 2nd element (fails the filter)
Tested: 8   // starting 3rd element
iter: 8     // ending 3rd element
Tested: 7   // starting 4th element (fails the filter)
...
Last Statement

These behaviors are explained more generally in the JavaDoc .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM