Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java 8 - Lazy Evaluation?

Tags:

java

java-8

I was going through a Streams Video when I found myself confused as to how Streams API was giving lazy evaluation over the imperative for loop approach.

Here's the typical for loop code which checks for the first number that is greater than three and even, it then simply prints it and returns.

List<Integer> arr = Arrays.asList(1, 2, 3, 5, 4, 6, 7, 8, 9);

    for (int i : arr) {
        System.out.println(" Checking if is Greater: " + i);
        if (i > 3) {
            System.out.println("checking if is Even " + i);
            if (i % 2 == 0) {
                System.out.println(i * 2);
                break;
            }
        }
    }

Here the expected output:

Checking if is Greater: 1
Checking if is Greater: 2
Checking if is Greater: 3
Checking if is Greater: 5
Checking if is Even 5
Checking if is Greater: 4
Checking if is Even 4
8

Now here's the same code using Streams API:

arr.stream()
       .filter(Lazy::isGreater)
       .filter(Lazy::isEven)
       .map(Lazy::doubleIt)
       .findFirst();

It too evaluates the same way. So how is filter() providing something different which we can't get using the traditional for loops?

like image 575
AgentX Avatar asked Nov 15 '15 14:11

AgentX


People also ask

Is there lazy evaluation in Java?

Lazy evaluation is another functional programming technique that is not new to Java 8. This technique delays the evaluation of an expression until its value is needed. In most cases, Java eagerly evaluates an expression that is bound to a variable.

Are Java 8 streams lazy?

The possibility of working on the infinite sequence of elements is predicated on the fact that streams are built to be lazy. This laziness is achieved by a separation between two types of the operations that could be executed on streams: intermediate and terminal operations.

Why are Java streams considered lazy?

Streams are lazy because intermediate operations are not evaluated unless terminal operation is invoked. Each intermediate operation creates a new stream, stores the provided operation/function and return the new stream.

What is a lazy operation in Java?

Lazy evaluation is an evaluation strategy which delays the evaluation of an expression until its value is needed. The opposite of this is eager evaluation, where an expression is evaluated as soon as it is bound to a variable.[wikipedia]


1 Answers

Here's the key: composability

arr.stream()
       .filter(Lazy::isGreater)
       .filter(Lazy::isEven)
       .map(Lazy::doubleIt)
       .findFirst();

That seems innocuous, but this is a value now:

 arr.stream()
       .filter(Lazy::isGreater)

You can hand it to a method and build on it.

What can do with an equivalent for loop? You can copy-paste it wherever you use it. It's not a composable abstraction.

Moreover, the Stream makes the how of iterating and processing the data abstract as well. It could with worker pools, or fork join, or it could go in an order favorable to CPU cache locality, or any number of things. You're no longer telling the JVM exactly how to do something you are getting closer to telling it what to do and letting it figure out how.

like image 114
Alain O'Dea Avatar answered Sep 26 '22 10:09

Alain O'Dea