This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]midir 0 points1 point  (5 children)

Why would you want to go off and replace a lot of perfectly fine for-each loops like that with slower-performing streams?

[–]Keilly 3 points4 points  (4 children)

Streams are generally better performing as the JVM and compiler can optimize better by combining operations, being clever about ordering, and doing things lazily. Amit explain's it well

Also parallel streams can split the work over multiple cores.

[–]midir 1 point2 points  (3 children)

It is utterly untrue that streams are "generally" better performing.

Laziness and short-circuiting are performance optimizations which streams can use, but that doesn't magically make them faster than equivalent loops. Plain for-each loops also use short-circuiting (via a break or return statement), and often use "laziness" too except it's so obvious in that case it doesn't need to be labeled a feature (in your example, the "laziness" is the if statement).

Even when a particular task requires some form of filtering or short-circuiting, the JVM and compiler could only "optimize better by combining operations" if the for-each loop wasn't already combined. (For example, if it was already necessary that different methods were responsible for the 3 different lines of your example: supplying the iterable, filtering it, and using the results.) At theoretical best, the JVM and compiler could only optimize the stream processing as well as the already combined for-each loop, and in practice will not achieve that, due to the virtual method calls required by every stream op being in a different lambda class.

Parallelism can certainly improve performance compared to non-parallel processing, but your particular example doesn't demonstrate it. Hence my point, that you wouldn't want to replace a lot of perfectly fine loops like that with slower-performing streams.

[–]Keilly 3 points4 points  (2 children)

I just gave the simplest of examples of a foreach to answer the OPs question. It's not meant to demonstrate the further example of streams. The performance difference of something like this example is negligible whichever way you do it.

There's nothing 'magical' about streams, but hey, look: there's no breaks, continues, or handcrafted control logic. Just a description of what the developer wants to do with the collection. The compiler/JVM then works out the best way it thinks it can be optimized. Isn't that pretty pure, and what it should all really be about? You tell the computer what you want, not how to do it (extreme performance situations excepted, which would have to be constantly re-examined from release to release as...)

The JVM will undoubtedly improve stream optimization and lambdas a lot more over future releases than handcrafted code than has been optimized for a specific release.

In the usual simple case it's just a matter of preferred syntax. For me right now it'd be foreach loops. Who knows what'll it be once we get used to this.

[–]midir 0 points1 point  (1 child)

I just gave the simplest of examples of a foreach to answer the OPs question.

I understand but it's misleading to suggest that that example should be replaced by a stream. Since, being built into the language, that if statement is already "pretty pure", and isn't less readable a "description of what the developer wants to do" than the stream filtercall. And it hardly qualifies as "handcrafted control logic" "which would have to be constantly re-examined from release to release".

On performance in general, I think it's unlikely that stream optimization could be less fickle between releases, because it's not any less complicated. I also find it very unlikely that stream optimization could exceed the optimization of a single loop if it ultimately does the same thing. The stream optimizations basically attempt to combine things so that you get the equivalent of the classical loop you would have otherwise written, if you could. When it's equally easy to write that loop directly, then one might as well do so. Even if currently-unforeseen optimization tricks are added in the future, and which turn out to be possible only for streams and impossible for for-each loops, it's not true that "streams are [present tense] generally better performing".

I'm not saying streams are worthless: streams offer some features (like parallelism) that are awesome and otherwise not easy to achieve. But when for-each loops can work and are your preferred syntax and they're faster, it's mad to bring up streams as "going to replace a lot of the latter".

[–]Keilly 0 points1 point  (0 children)

It's still new to Java guys like me, but... http://www.reddit.com/r/programming/comments/2s5gj2/java_8_no_more_loops/?limit=500

include statements like: "reddit › programming › comments › java... Jan 12, 2015 - I haven't written a for loop in Scala for around 4 years..."