• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Fun with streams and higher order functions

 
Bartender
Posts: 5465
212
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
(Original thread. -Stephan van Hulst)

Hmm... yes, but I'll let his Royal Javanesses Sirs Campbell and Winston deal with that

But earlier, I mentioned something about using the GroupingBy method.
The wife went shopping yesterday afternoon, so I took the opportunity
to download NetBeans and Java 8 on her W7 laptop.

I spent the whole evening trying to get the groupingBy method to work,
to an extent that I got nearly mad, and reading the API on Stream.collect,
Collectors and all thse millions of type wildcards, and reading the tutorials,
finally this morning I got something. Here goes:

But I must say: having now had my first experience with Streams, I find it not
an easy or intuive going...

Greetz,
Piet
 
Saloon Keeper
Posts: 15510
363
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Streams become much more intuitive after you've worked with a lazy functional language. You shouldn't regard streams as a weird type of collection, instead they're just sequences of operations that get performed on a collection.

Piet, your code groups characters by whether or not their value is even. The problem was to get which numbers represented in the stream were even or odd. That means you have to filter out non-numeric characters first. Here's how you could do it with the groupingBy operation:
You'll see that Mike's version is much more elegant.
 
Bartender
Posts: 10780
71
Hibernate Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Piet Souris wrote:But I must say: having now had my first experience with Streams, I find it not
an easy or intuive going...


Welcome to functional programming.

The way I think of it is like a pipeline of scripts. A while ago, I wrote a "javadoc"-type suite for publishing documentation for other scripts in HTML form. Basically, it was just pipeline of about 6 scripts, each of which simply filtered or formatted the result of the previous script; and it worked really nicely because each script was written to do a single task.

Java's implementation is slightly clunky (and TBH, the class docs aren't really much use; I hope they improve that in future releases), but I suspect that's because the language wasn't really designed for functional processing.

That said, I really like the idea; and you can bet I'll be using String.chars() and Collection.stream() quite a bit once I've got my head around it all and it's a bit more mature.

Winston
 
Piet Souris
Bartender
Posts: 5465
212
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Stephan van Hulst wrote:(...)
Piet, your code groups characters by whether or not their value is even. The problem was to get which numbers represented
in the stream were even or odd.(...)


I know, but my intention was to come up with a way to split an array into two parts. As such, the code was only meant as
an example. No more, no less. I was thinking specifically of the partition method on Lists in Scala.

Streams become much more intuitive after you've worked with a lazy functional language. You shouldn't
regard streams as a weird type of collection, instead they're just sequences of operations that get performed
on a collection.



Well, I've tried to see the similarities between a Scala Stream and a Java one.
In Scala, a Stream is a genuine data structure, with lazy evaluation of its tail
as its main characteristic.
In Java, a Stream is not a data type, and maybe lazyness plays a role, but in
the examples I've seen so far, no use of it was made. Well, not that I noticed.

But then again, I've now one day experience with Java streams, and I think I
might need a 'couple of days more' to get acquainted with the subject...

Greetz,
Piet
 
Piet Souris
Bartender
Posts: 5465
212
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Winston Gutkowski wrote:
Welcome to functional programming.

(...)


Yes, I like Java streams, in combination with the use of lambda's.
They certainly can make for elegant code.
And I agree: the API's are a disaster to read, but well, it keeps you off
the streets.

And lastly: I do think Java's way of implementing a form of
functional programming, by using functional interfaces, is clumsy,
but maybe there was no other way. Then again, if Scala and Haskell
can do it, so should Java.

Greetz,
Piet
 
Stephan van Hulst
Saloon Keeper
Posts: 15510
363
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Piet Souris wrote:In Java, a Stream is not a data type, and maybe lazyness plays a role, but in
the examples I've seen so far, no use of it was made. Well, not that I noticed.



And how would you notice? You can only get results from a stream by evaluating it. Non-terminating operations (such as filter, map, etc.) are lazy. Terminating operations (such as collect, sum, foreach) are not lazy, because you need a result!

I think the biggest issue of streams is that you can't pipe operations together if you don't already have a source stream. For instance, Haskell has the function composition operator, which makes it really easy to compose a function like the one in the original problem:
ghci> getOddValues "ODear 12340 et cetera 6 7"
[1,3,7]
 
Piet Souris
Bartender
Posts: 5465
212
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Stephan van Hulst wrote:

Piet Souris wrote:In Java, a Stream is not a data type, and maybe lazyness plays a role, but in
the examples I've seen so far, no use of it was made. Well, not that I noticed.



And how would you notice?(...)


Risking getting too far off topic, a classic example would be to find the third
prime number after, say, 10.000, for which lazyness is very well suited.

ghci> getOddValues "ODear 12340 et cetera 6 7"
[1,3,7]


Very powerfull indeed. It is this kind of power that I'm looking for in Java,
and whether streams are the way to go, or simply some methods with
predicates, I don't know, so I try do do as much experiments as I can,
gaining knowledge as I go.

Greetz,
Piet
 
Stephan van Hulst
Saloon Keeper
Posts: 15510
363
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

The above would obviously not work if iterate() wasn't lazy.

Seeing as we're going wildly off topic, I'll split the thread.
 
Stephan van Hulst
Saloon Keeper
Posts: 15510
363
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
The same in Haskell would be:

take 3 [x | x <- [10001, 10003..], isPrime x]
 
Piet Souris
Bartender
Posts: 5465
212
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Stephan van Hulst wrote:
The above would obviously not work if iterate() wasn't lazy.

Seeing as we're going wildly off topic, I'll split the thread.


Yes, we were a bit off topic.

Very convincing example. I also tried

Great stuff, this is!

Greetz,
Piet
 
Stephan van Hulst
Saloon Keeper
Posts: 15510
363
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
The one truly sucky thing about Streams is that they can not be operated on more than once. One could have used findFirst() to get the head of the stream, and skip(1) to get the tail of the stream, but you can't use them both.
 
Consider Paul's rocket mass heater.
reply
    Bookmark Topic Watch Topic
  • New Topic