4 ms·
That example could be easily written like this: var num = words.stream().filter(w -> !w.isEmpty()).count(); This is shorter and closer to what you're expe
by mike_hearn 3y ago
That example could be easily written like this:
var num = words.stream().filter(w -> !w.isEmpty()).count();
This is shorter and closer to what you're expecting. The reason it's written the long way is because of the labels. The prior sentence is:
A stream pipeline consists of three parts: a source of elements, any number of intermediate operations, and a terminal operation. For example: ...
so the goal here is to make the different components of the pipeline clear conceptually for the explanation of what's to come, not to write the shortest code possible. It therefore uses code that makes the underlying abstractions explicit rather than the sugar that avoids typing.
The reference to "expressive and efficient" meanwhile is likely about the fact that Java can parallelize streams in many cases (efficient). As for "expressive", well, that's somewhat debatable but for sure there are some cases where the functional pipeline style is easier to read and more expressive than the imperative style. In my own code I use both because indeed especially for short operations over lists and the like, sometimes a for loop is just clearer to my eye. But it's a matter of taste.
BTW the same code written in Kotlin:
val num = words.filter { !it.isEmpty() }.count()
Very similar. You may slightly prefer the syntax or dislike the "magical" auto-naming of the lambda parameter, I've seen it argued both ways.
----
https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/stream/Stream.html#count https://docs.oracle.com/en/java/javase/21/docs/api/java.base...()
- kaba0 3y agoI think Scala is hands down the best collections/stream library, I especially like their _ shorthands: val num = words.count(!_.isEmpty())
- Marazan 3y agoI think that is a horrifying crime against man and nature. If I wanted to write PERL I would do so.
- kaba0 3y agoWhat is hard to understand about it? _ is universally used as a placeholder, it also usable in pattern matching. Scala can be used to make some perl-y <!! operators, but it is not like that at all, and makes for very readable, understandable code.
- haspok 3y agoAlso targeted at Java 22: https://openjdk.org/jeps/456 https://openjdk.org/jeps/456 (Unnamed Variables & Patterns)
- skrebbel 3y agoSame, I wish more languages had that shorthand
- layer8 3y agoUnderstanding bird droppings like “!_.()” relies on quite some prerequisites.
- kaba0 3y ago! contradicts a boolean. _.isEmpty() is a lambda, applying the isEmpty function on its string parameter. It’s just the two things together.
- layer8 3y agoI know all this. But as I said, pulling it all together involves quite a number of concepts represented by idiosyncratic punctuation, much more than “count all non-empty elements”.
- kagakuninja 3y agoThen your team can write lambdas in a more verbose, but less cryptic style.
- philipkglass 3y agoWhen I was introducing a team to Scala I wrote everything in a more verbose style just to make it clear, e.g. val num = words.count(word => word.nonEmpty) The "bird droppings" (particularly the clever uses of _ found across Scala) were hard for me to grasp when I first started working in the language. Now they're second nature, but I try to remain cognizant of future maintainers who may be coming in to make contributions or bug fixes without first marinating in the language.
- dionian 3y agoThe nice thing is you can just write it like `x => !x.isEmpty` if you want
- sedro 3y agoOr more succinctly val num = words.count(_.nonEmpty)
- jillesvangurp 3y agoKotlin has lots of nice features for this kind of stuff. Including extension functions and it comes with lots of those for existing Java APIs. And a nice thing with extension functions is that they also work against interfaces, generic types, etc. So, there is no need for a Stream.of in Kotlin. You just call .filter, .map, etc. on anything that you'd want to call that on that is a List, Map, Array, Flow, Sequence, whatever. Java Streams too probably but I haven't had a need for using those in five years. As for doing things in parallel, that's where Kotlin co-routines shine.
- mjburgess 3y agoWell, my comment was more about it being a bit funny as an opening example to be described as expressive and efficient -- given how overly namespaced and partitioned the presentation of the API is. I can appreciate its essentially a desugared version of what you'd usually write. The JEP doesnt need to be positioned to defend this API to outsiders, but the opening part appears to do that -- but then, imv, oddly offers this example in the course of doing so.
- bardsore 3y agoThe kotlin example can be made even more concise: val num = words.count { it.isNotEmpty() }