Introduction
Functional programming is a programming paradigm that promotes the use of functions and the avoidance of changing state and mutable data. This style of programming can lead to more concise, expressive, and maintainable code. The best way to start making use of it is by using the Java Streams API.
Java, being one of the most widely used programming languages, has also adopted functional programming concepts and features. In this post, we will take a look at how functional programming can be applied in Java 8 using the Streams API and functional interfaces.
Functional programming has several benefits over imperative programming, such as:
- It promotes immutability, which means that data cannot be modified once it has been created. This can lead to fewer bugs and a more predictable program.
- It encourages the use of pure functions, which are functions that always return the same output for the same input, and do not have any side effects. This can make code more testable and reusable.
- It allows for the creation of higher-order functions, which are functions that take other functions as input or return functions as output. This can lead to more expressive and reusable code.
The Streams API
The Streams API is a powerful and flexible API that allows you to perform operations on collections of data in a functional way. It provides a fluent API for working with collections of data, such as filtering, mapping, and reducing.
Java Streams 101
First things first, if you are reading this article, chances are this is one of the first times you’re hearing about functional programming. If that’s your case, let me introduce you to one easy concept you must understand in order to master the use of the Streams API.
I’m talking about terminal vs intermediate operations. You have to think of Streams as a pipeline, each operation performed by a Stream either terminates or not the Stream.
Some examples of non-terminal (or intermediate) operations are:
- map -> Transforms the Stream from type A to type B.
- filter -> Filters the elements in the Stream.
- limit -> Limits the elements in the Stream.
All those functions do not terminate the stream and as a result, they return another stream. That is to say, they perform some operation for the given stream and return a different stream.
Some examples of terminal operations are:
- collect -> Collects the elements in the stream (usually to a List)
- forEach -> Perform an operation for each element in the stream
Those functions terminate the stream and thus, they require a semicolon as a regular line of code ender in Java.
Now, let’s talk next about the most basic -yet most used- Stream’s functions.
Map
I would probably say it’s the most useful and the first Stream function any programmer should learn.
Have you ever experienced having a list of objects, let’s say of class Animal
, and wanted to iterate through the list just to collect some property (such as name, age, color…)?
Most of the Java developers would probably create a new ArrayList
for storing this property, iterate the list, probably using a for-loop and collect the given property in the new list. Something like this:
Was I close to what you were expecting? I guess so.
Quick disclaimer! There’s nothing wrong with this approach, I’ll write a post regarding whether you should use streams over loops. For the sake of this post, let’s just say there are multiple available approaches up to you.
If you wanna read more about this, feel free to look for some information yourself. This can be your starting point though.
Now, this could be easily done as well with Java streams like so:
In this example, we are leveraging the existence of the map
function. As a non-terminal operation that takes a lambda expression as the argument, it transforms the given Stream, in this case from type Animal to type String. In this case, we’re specifying that for each animal in the animals
list, it should be mapped to a string, by using its property name
and then collecting everything to a list that is returned.
You can also use the method reference of the Animal
class
Notice as well that there’s no need for curly braces when the lambda expression is a one-liner.
Filter
Another function you should be familiar with. It expects a Predicate
(don’t worry about it, it’s basically a lambda expression/method reference) as an argument to filter the given stream. Since it’s a non-terminal operation, it returns another stream. This is one of the main benefits of using the Streams API, being able to chain call.
Easiest example ever, given a list of integers, return those that are greater than 10:
ForEach
This one is a terminal operation and as so, it ends the stream. It expects a Consumer
which as a function that will be performed to each of the elements in the Stream.
Let’s say that for each filtered number of the previous example, we want to output it to the console, instead of adding it to a list:
Some more examples
Let’s say we have a list of integers and we want to find the sum of all even numbers in the list. With the Streams API, we can do this in a single line of code:
In this example, we first create a stream of the list of numbers, then use the filter method only to keep even numbers, then we use the mapToInt method to convert the stream of Integers to a stream of primitive ints, and finally, we use the sum method to find the sum of all numbers in the stream.
Functional interfaces are another functional programming feature introduced in Java 8. They are interfaces that have a single abstract method, such as Predicate
, Function
, and Consumer
. These interfaces can be used to create lambda expressions and method references that can be passed as arguments to methods.
For example, let’s say we have a list of strings and we want to print all strings that are longer than 3 characters. With functional interfaces, we can do this in a single line of code:
In this example, we first create a list of strings, then we use the forEach method and pass a lambda expression that checks if the length of a string is greater than 3, and if so, it prints the string.
Conclusion
Functional programming is a powerful and expressive way to write code, and with the introduction of the Streams API and functional interfaces in Java 8, it’s now easier than ever to write functional code in Java. While it’s not always the best solution for every problem, understanding the concepts of functional programming is an extremely important tool for every Java developer.
At first, you might want to give it a try and practice this new way of thinking. Once you get used to it, you will realize the high potential of using functional programming.
Everything is very open with a really clear clarification of the issues. It was definitely informative. Your website is extremely helpful. Thanks for sharing!
Thank you so much for your kind words, I hope you keep enjoying this kind of content. I’ll do my best to keep bringing it 😃
May I simply just say what a comfort to uncover an individual who actually knows what they are talking about on the web. You definitely know how to bring a problem to light and make it important. More people need to look at this and understand this side of the story. I was surprised that you arent more popular because you most certainly have the gift.
Nice post. I learn something totally new and challenging on sites I stumbleupon everyday. It will always be exciting to read content from other writers and practice a little something from other sites.
A motivating discussion is definitely worth comment. I think that you should publish more on this subject matter, it may not be a taboo matter but generally people dont discuss these topics. To the next! All the best!!
A motivating discussion is worth comment. I do believe that you should write more on this subject matter, it might not be a taboo subject but generally people do not talk about these subjects. To the next! Best wishes!!
I must thank you for the efforts you have put in penning this site. I really hope to view the same high-grade blog posts by you in the future as well. In fact, your creative writing abilities has encouraged me to get my very own website now 😉