Functional Programming in Java - Venkat Subramaniam: Book Review
I picked up Venkat Subramaniam’s 'Functional Programming in Java: Harnessing the Power of Java 8 Lambda Expressions' to learn a little bit more about Java 8 having struggled to find any online tutorials which did that.
A big chunk of the book focuses on lambdas, functional collection parameters and lazy evaluation which will be familiar to users of C#, Clojure, Scala, Haskell, Ruby, Python, F# or libraries like totallylazy and Guava.
Although I was able to race through the book quite quickly it was still interesting to see how Java 8 is going to reduce the amount of code we need to write to do simple operations on collections.
I wrote up my thoughts on lambda expressions instead of auto closeable, using group by on collections and sorting values in collections in previous blog posts.
I noticed a couple of subtle differences in the method names added to collection e.g. skip/limit are there instead of take/drop for grabbing a subset of said collection.
There are also methods such as 'mapToInt' and 'mapToDouble' where in other languages you’d just have a single 'map' and it would handle everything.
Over the last couple of years I’ve used totallylazy on Java projects to deal with collections and while I like the style of code it encourages you end up with a lot of code due to all the anonymous classes you have to create.
In Java 8 lambdas are a first class concept which should make using totallylazy even better.
In a previous blog post I showed how you’d go about sorted a collection of people by age. In Java 8 it would look like this:
List<Person> people = Arrays.asList(new Person("Paul", 24), new Person("Mark", 30), new Person("Will", 28));
people.stream().sorted(comparing(p -> p.getAge())).forEach(System.out::println)
I find the 'comparing' function that we have to use a bit unintuitive and this is what we’d have using totallylazy pre Java 8:
Sequence<Person> people = sequence(new Person("Paul", 24), new Person("Mark", 30), new Person("Will", 28));
people.sortBy(new Callable1<Person, Integer>() {
@Override
public Integer call(Person person) throws Exception {
return person.getAge();
}
});
Using Java 8 lambdas the code is much simplified:
Sequence<Person> people = sequence(new Person("Paul", 24), new Person("Mark", 30), new Person("Will", 28));
System.out.println(people.sortBy(Person::getAge));
If we use 'forEach' to print out each person individually we end up with the following:
Sequence<Person> people = sequence(new Person("Paul", 24), new Person("Mark", 30), new Person("Will", 28));
people.sortBy(Person::getAge).forEach((Consumer<? super Person>) System.out::println);
The compiler can’t work out whether we want to use the forEach method from totallylazy or from Iterable so we end up having to cast which is a bit nasty.
I haven’t yet tried converting the totallylazy code I’ve written but my thinking is that the real win of Java 8 will be making it easier to use libraries like totallylazy and Guava.
Overall the book describes Java 8’s features very well but if you’ve used any of the languages I mentioned at the top it will all be very familiar - finally Java has caught up with the rest!
About the author
I'm currently working on short form content at ClickHouse. I publish short 5 minute videos showing how to solve data problems on YouTube @LearnDataWithMark. I previously worked on graph analytics at Neo4j, where I also co-authored the O'Reilly Graph Algorithms Book with Amy Hodler.