File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes Features new in Java 8 and the fly likes Fun with streams and higher order functions Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Spring in Action this week in the Spring forum!
JavaRanch » Java Forums » Java » Features new in Java 8
Bookmark "Fun with streams and higher order functions" Watch "Fun with streams and higher order functions" New topic
Author

Fun with streams and higher order functions

Piet Souris
Ranch Hand

Joined: Mar 08, 2009
Posts: 650
    
  11
(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
Stephan van Hulst
Bartender

Joined: Sep 20, 2010
Posts: 3647
    
  17

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.
Winston Gutkowski
Bartender

Joined: Mar 17, 2011
Posts: 8008
    
  22

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

Isn't it funny how there's always time and money enough to do it WRONG?
Articles by Winston can be found here
Piet Souris
Ranch Hand

Joined: Mar 08, 2009
Posts: 650
    
  11
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
Ranch Hand

Joined: Mar 08, 2009
Posts: 650
    
  11
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
Bartender

Joined: Sep 20, 2010
Posts: 3647
    
  17

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
Ranch Hand

Joined: Mar 08, 2009
Posts: 650
    
  11
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
Bartender

Joined: Sep 20, 2010
Posts: 3647
    
  17


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
Bartender

Joined: Sep 20, 2010
Posts: 3647
    
  17

The same in Haskell would be:

take 3 [x | x <- [10001, 10003..], isPrime x]
Piet Souris
Ranch Hand

Joined: Mar 08, 2009
Posts: 650
    
  11
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
Bartender

Joined: Sep 20, 2010
Posts: 3647
    
  17

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.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Fun with streams and higher order functions