I have been playing with the new and shiny functional part of Java and one of the things that puzzle me the most are streams?
What is their use?
On Google I mostly found explanations of how to use them and practical examples, which I already got down, nothing concrete about the magic behind the scenes, which is what interests me.
I dont mean in a practical sense, coming from a few functional languages i figured out map/filter/reduce/etc. fairly quickly but why do we need to convert to a stream first? Java already has iterators. Is there a fundamental difference between stream and iterator like one being lazy and the other not? Or is it something else?
Bottom line: what is the fundamental difference between iterators and streams and what functionality couldn't be implemented as an extension to iterators and needed a whole new family of types?
Talking about streams, in general, is a vast topic. However, I will derive about why you should favour the streams API over Iterators.
First and foremost, with the stream API, we can now program at a much higher level of abstraction, just like SQL queries, i.e. we express what we want and let the library handle the rest.
Second, stream operations perform their iterations behind the scenes (internal iteration) , this means the processing of the data could be done in parallel or in a different order that may be more optimized.
On the other hand, if you decide to explicitly iterate over your collection to perform some computation whether that's with an Iterator or the syntactic sugar for an iterator (the enhanced for loop) then you're explicitly taking the items in the collection and processing them one by one thus it's inherently serial.
Using iterators instead of the stream API also means a lot more work has to be done when you want to go parallel or find different ways to optimise your program.
Yet, this also means that you're spending much more time dealing with the low-level details instead of just focusing on what you want your program to do.
Also mentioned in the Java-8 in Action book:
The internal iteration in the Streams library can automatically choose a data representation and implementation of parallelism to match your hardware. By contrast, once you’ve chosen external iteration by writing for-each, then you’ve essentially committed to self-manage any parallelism. (Self-managing in practice means either “one fine day we’ll parallelize this” or “starting the long and arduous battle involving tasks and synchronized”.)
Java 8 needed an interface like Collection but without iterators, ergo Stream!
Essentially, with the stream API, your life is much easier in many ways but what I find most useful is the fact that you can now put more time into focusing on what you want your code to do and at the same time you can decide to go parallel without dealing with the low-level stuff.
This is of course not saying to always utilise streams wherever/whenever possible. Rather it's stating the benefits of using streams over Iterators.
There are certain places where it will be more appropriate to use Iterators rather than the stream API and vice versa. So choose wisely which approach to proceed with in terms of processing data in collections.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With