I’m back to writing a lot of Java (and now Kotlin) over the last year from working on Android Studio. That’s been surprisingly enjoyable due to new features in Java 8 (like streams) that weren’t available last time I work on JVM in 2013.

Quick background on Java 8 Streams

Streams allow you to turn Java collections into a sequence that can be operated on with functional operators (map, reduce etc). This lets you write code closer to a functional paradigm rather than a procedural one.

I’ll show an example of the same method written in these 2 styles:

This method operates on a list of integers and does some filtering + transforms and returns another list. Let’s compare the procedural businessLogic vs the functional style of businessLogicFunctional.

1.Functional version is more concise.

The functional version has less lines (12 vs 6) and each line is also short. The overall function has less levels of indentation.

2. Functional version is more readable.

Conciseness does not always equal clarity of code. However in this case, the functional version is much clearer. Generally operating on collections through map/filter/reduce etc are more readable than loops.

The issue with loops is the read has to store context while reading the code. In the procedural version on line 16 it starts a loop with index i, then every line inside the loop requires keep track of that state. This can get complex quickly with multiple loops and if statements.

In the functional version, there is little state to track. Each operation is performed in the order they are written from left to right. it’s a filter, then a map, then another filter and you’re done.

More importantly, each step is limited in what it can do. Filter removes elements that doesn’t meet the predicate. Map does a 1 to 1 transformation on the element.

This is known as avoiding side effects and that’s strongly encouraged in functional programming.

Any operation on collection of data can be written in a functional style and it will generally result in better code that is easier to understand and change.

Given a collection of elements of size N, you can transform the data however you wan through the following operations:

N -> N:

use map to transform each element and get a new collection of transformed data.

N -> M:

you want to map each element in the collection to 0 or more elements? the use flatMap. Like the name suggests, it’s a flatten map.

So if you have a list of ints like so: [1,2,3]

and you want to map each element i to an array of 1 to i, so:

1 => [1], 2 => [1,2], 3 => [1,2,3]

map will return: [[1], [1,2], [1,2,3]]

whereas flatMap will return: [1,1,2,1,2,3]

N -> 1:

You have a collection and you want to reduce it to a single element. Use reduce on it and it’ll take a starting value, and a method takes consumes the element 1 by 1 until it goes through the whole collection and returns a single result.

Now, what if you have a collection and you want to process it to return 1 or more results? Take this example:

Given an array of positive integers less than 1000 of size N, return calculate the sum of values in N between 1 to 100, 101 to 200, 201 to 300 etc.

A common programming quiz problem. At first glance you might say: “You have to sort the values into buckets and then sum each of the buckets! Can’t do that functionally. Time to go back and write a procedural method”.

Actually, that’s what the Java collectors are for. You saw it being used in businessLogicFunctional at the end to collect the stream back into a List. There are a lot of other collectors that collects by different logic.

In this case, we can use the groupBy collector:

That was my quick overview on functional programming in Java using streams. I’ll leave you with this challenge that I’ll answer in my post on custom collectors:

You are given a file with N lines. You need to parse the file and return a collections of Foo objects. If you see a line of all equal signs, you’re to create a new Foo object. For all other lines, append that to Foo’s output string field.

Have fun!