Functional Programming in Java 8

In this article we will talk about how to exploit the Functional paradigm in a Object-oriented programming language like Java 8. At the end, I will show how to grant parallelism to our software in an easy way.

But first, let’s recap the differences between the programming paradigms we are taking in consideration: Imperative, Logic, Functional and Object-oriented.

Imperative Paradigm is about a series of commands sent to the machine one after the other, executed exactly in the order they have been written. This paradigm is called Imperative because the developer has to express all the passages to achieve the solution.

Logic Programming allows the developer to write only what the machine has to do, without the necessity of express how the result should be achieved. In this way, the human can just think about logical function of the software, without the need of think about implementation details.

Functional Paradigm (FP) is an extension of Logic Paradigm, that uses functions in order to obtain the desired output. In the imperative approach the variables can mutate and so can the state of the program. On the contrary, in functional (and logic) paradigm, the variables are immutable. New states of the program are created starting from the old states, without their modification. Moreover, functions can also be sent as input and output (first-class functions).

In Object-oriented Paradigm (OOP), entities called objects, can interact with each other through messages. Nowadays this type of paradigm is the most used because it perfectly reflects the human thinking. Furthermore, OOP is the best approach to manage large projects.

 

Example of a set of programming paradigms.

Listed below are the three main reasons why Functional Paradigm should be used instead of Imperative Paradigm in Java:

  1. Easier maintainability and better understanding of the code
  2. Simplified refactoring
  3. Easier test & debugging

Nowadays, modern languages and frameworks that exploit functional and object-oriented paradigms have a major impact within developers community. Some examples are Scala, and JavaScript frameworks like AngularJS and ReactJS (ES6).

Java has introduced Functional Paradigm in Version 8, in order to compete with these new modern languages. Let’s go deep into these changes and let’s see how to use the functional approach in Java 8.

Example

Let’s create a list (which implements Iterable) and print its values through an external iteration:

or even better, we can avoid wasting a variable on the loop:

or we could use functional paradigm and lambda expressions and write a cleaner code, for example by using internal iteration, like this:

Let’s take a look at the interface Stream, which is the main character of this functional paradigm update.

Java 8 Stream

The Stream interface allows us to abstract the code in a declarative way. To create a stream from a Collection, we can simply call the method stream on it:

We can then perform a number of operations, called intermediate, that return a new Stream object, without modifying the input one. At the end of these, we can call a terminal operation in order to return Void, or any non Stream type. I.e., filter, map and sorted are intermediate, while reduce and forEach are terminal paradigms.

We remind that any operation executed on a Stream object does not modify its state, but instead it generates a new Stream. In this way, the state of the program is immutable. At each step, a new stream is then generated from a method in order to reach the final state of the program.

Example

The problem we want to solve consists of printing the elements of a list that are even, multiplied by a variable.

It follows the imperative approach:

Let’s resolve the problem with the use of Stream:

What the previous piece of code does, can be read through the lines:

  1. create a stream of list
  2. filter the stream: take only even numbers
  3. map the stream: multiply each member to filter
  4. for each member: print it

Recall that each of the intermediate methods return a new stream, so i.e., filter cleans the given stream, and it returns a new one. At the end,  forEach returns Void and prints every even number in the list multiplied by 3, which are in the right order: 6, 12, 18.

Input, output for .stream(), .filter(), .map() and .forEach() methods.

From the previous example it is evident that by using Functional Paradigm we can avoid possible errors due to wrong mutabilities of variables or misunderstanding of the code. In this way, we can easily read and extend the software.

Also, it is possible to parallelize each operation on a stream thanks to parallelStream method. We can then simply use more cores on our code just by substituting .stream() with .parallelStream(). Don’t use it if you need the output in a specific order, because of course by parallelizing a function you don’t know the exact order of the output.

Let’s see the previous example with the use of parallelStream:

 

In conclusion, today we had a look at functional approach in Java 8 and we have discussed why this method can improve your code. Are you already using it? Are you more an imperative or functional approach coder?

 

Good Refactoring!

(Visited 78 times, 1 visits today)

Leave A Comment

Your email address will not be published. Required fields are marked *