Functional Java: Should I really start using the functional paradigm in Java?

Reading Time: 5 minutes

I am pretty sure, at some point, you must have had this question in your mind because everywhere, it is functional programming, immutability, higher-order functions, and blah blah.

As a java developer, you must have confused, whether should I move to the functional programming paradigm? What are the benefits it provide to us? People are talking about it everywhere. So let’s give it a try once and then you can decide whether you should go to the functional paradigm or not.

We will see the functional programming features one by one with the code examples and will compare it with the imperative way of java programming.


Mutable variables are poor in taste, and shared mutable variables are pure evil. We often get confused or overlook change to variables. As a result, code with more mutable variables tends to have more errors. Code with shared mutable variables is very hard to parallelize and very hard to reason about. One way to reduce errors is simply to avoid mutability wherever possible, and the functional style makes that easier.

Example: Get the sum of double of each element of a list.





In imperative one, we are mutating the sum variable but the functional one is pure immutable.


We have to raise the level of abstraction. Instead of focusing on the “How” part, we should focus on the “What” part. With this, we would be able to focus on the business logic only and can increase productivity.

Example:  Get the sum of double of each element of a list.





In imperative one, we are telling to compiler each and every step. How to loop through, from where loop should start, where it should end, double the element and then add it to the sum. A lot of stuff to think about. While in the functional, we just need to think of the business logic. That’s it.

Pure Functions:

A function or method with side effects is hard to understand, hard to maintain, more error-prone, and difficult to parallelize. If we remove side effects, then as long as the input to a function remains unchanged, the output will always be the same.

Having no side effects is critical for referential transparency, which means an invocation or a call to a function can be replaced by its result value without affecting a program’s correctness. With the referential transparency, the compiler can optimize the calls.  Functions that have side effects impose ordering and restrict optimization. On the other hand, calls to functions with no side effects can be moved around and reordered more freely.

Impure Function:


Pure function:


Impure Lambda:


Pure Lambda:


Higher-Order Functions:

In Java 8, one of the biggest changes we have to make is to design with higher-order functions. We’re used to passing objects to methods, return objects from a function but now we have the ability to pass functions as arguments and return a function from a function.

This is because, earlier objects used to be first-class citizens but now functions can also be the first-class citizens. This gives us a more concise code: anywhere we passed anonymous inner classes to a single method interfaces, we can now pass lambda expressions or method references.

Anonymous inner class:





Java already uses lazy execution when evaluating logical operations. For example, in fn1() || fn2() , the call fn2() is never performed until fn1() returns a boolean true. Likewise, if we replace the || with && , the call to fn2() never happens until fn1() returns a boolean false. Programs benefit from this short-circuiting; we avoid unnecessary evaluation of expressions or functions, and that can help improve performance.

Java evaluates logical operators lazily but what if we want method arguments to be evaluated lazily as well. Before Java 8, it was not possible but now with the help of Lambda, we can make it possible. Lambda gets evaluated lazily.

Let’s look into the below class:


We have 2 functions in the above class:

eagerEvaluator() : It evaluates the argument eagerly

lazyEvaluator(): It evaluates the arguments lazily.

Let’s call them one by one and see the output:

eagerEvaluator(evaluate(1), evaluate(2));



lazyEvaluator(() -> evaluate(1), () -> evaluate(2));



By looking at the above outputs, we can easily see the difference.

We can get the laziness with the help of Java Streams too. Streams are having 2 types of operations: Intermediate and Terminal. Streams do not get evaluated until we call the terminal operators.

This is all about the functional features in Java.

After looking at the above features, we can easily say that yes, we should start writing code in a functional way in java because we get the following benefits from the code perspective:

  • Easy to read and understand
  • Easy to maintain
  • Easy to reason
  • Less error-prone
  • Improve testability
  • Easy to parallelize

I hope this blog will give you some insights to choose between the imperative and functional programming paradigm in Java.

If you really want to learn more about functional java, see the more code examples here.

References: Functional Programming In java book by Venkat Subramaniam.





Written by 

Rishi is a tech enthusiast with having around 10 years of experience who loves to solve complex problems with pure quality. He is a functional programmer and loves to learn new trending technologies. His leadership skill is well prooven and has delivered multiple distributed applications with high scalability and availability by keeping the Reactive principles in mind. He is well versed with Scala, Akka, Akka HTTP, Akka Streams, Java8, Reactive principles, Microservice architecture, Async programming, functional programming, distributed systems, AWS, docker.

1 thought on “Functional Java: Should I really start using the functional paradigm in Java?4 min read

Comments are closed.