Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala Stream vs Java Stream Laziness Difference

I'm new to the concept of lazy evaluation. When I execute this line of code in Scala;

"12334".grouped(1).toStream.filter{n => println("n:" +n ); n=="3";}

It prints out:

n:1
n:2
n:3

But when I run something similar in Java, like:

List<String> myList = new ArrayList<>(Arrays.asList("12334".split("")));

Stream<String> myList2 = myList.stream().filter(a -> {System.out.println("a:" +a);return "3".equals(a);});

It terminates silently without writing anything to console line. Java's behavior seems more reasonable to me because Streams are lazily evaluated and I did not collect or try to print result. But in Scala even if I did not consume stream it prints out some information. So my question is what is causing that difference?

like image 647
altayseyhan Avatar asked Jan 20 '17 12:01

altayseyhan


People also ask

Are streams in Java lazy?

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.

Does Java stream improve performance?

In Java8 Streams, performance is achieved by parallelism, laziness, and using short-circuit operations, but there is a downside as well, and we need to be very cautious while choosing Streams, as it may degrade the performance of your application.

Are Java streams more efficient than for loops?

Remember that loops use an imperative style and Streams a declarative style, so Streams are likely to be much easier to maintain. If you have a small list, loops perform better. If you have a huge list, a parallel stream will perform better.

What is Scala stream?

The Stream is a lazy lists where elements are evaluated only when they are needed. This is a scala feature. Scala supports lazy computation. It increases performance of our program. Streams have the same performance characteristics as lists.


1 Answers

It's due to the fact that filter isn't entirely lazy. It has this piece of code:

while (!rest.isEmpty && !p(rest.head)) rest = rest.tail

Which causes materialization and actual filtering of the Stream.

If you want full laziness, go with withFilter:

"12334".grouped(1).toStream.withFilter { n => println("n:" +n ); n=="3"; }

For more see withFilter instead of filter.

like image 120
Yuval Itzchakov Avatar answered Sep 21 '22 01:09

Yuval Itzchakov