Sign in
Log inSign up

An Introduction to Functional Programming in Java

Sonali D's photo
Sonali D
·Dec 23, 2020·

5 min read

After Java introduced the Java 8 version, the primary structure of the language shifted from the original OOPS concepts to functional programming. Java, originally, is an object-oriented programming language. It works on four major paradigms: encapsulation, polymorphism, abstraction, and inheritance. Working on these four paradigms means the entire Java language revolves around the functionality of objects. A class defines an object and its properties along with functions that call out its behavior. But with the advent of Java 8, the structure is based more on behavior than objects.

What is functional programming? Functional programming is a paradigm that takes complex computation as the evaluation of mathematical functions (lambda expressions) which makes the code easier to understand, less complex, and reasonable to test. The original Java programming language is based on Von Neumann architecture. The biggest problem of using object-oriented or imperative programming is the mutability and complexity. Functional programming pacifies these problems and works more on expressions than statements. Its concepts are primarily based on immutability (the state cannot be changed) and pure function. Also to further consolidate your knowledge and concepts in Java, here's a link to the most commonly asked java interview questions.

Concepts in functional programming Functional programming works on four concepts in Java 8: 1. Lambda Expressions: Lambda expressions lets a function (method) pass as an input parameter for another function. Although, first-class functions allow to pass a function as a parameter assign a function to a variable, or return a function value from another function but as Java doesn’t support this, lambda expressions are the closest to this functionality. Lambda expressions form the basis of functional programming and have minimum support to mutability. It has only a parameter list and a body. Lambda function comprises two parts separated by a ‘->’. Parameter -> { function body }

The mentioned example prints every item in the list: Output: 1 2 3 4

1.png

2.Functional interfaces: A functional interface has one abstract method ie. a method that has not been instantiated. An interface might contain a static method, default method, or an abstract method but if an interface contains only one abstract method, it is referred to as a functional interface. 3.Optional class: Optional classes are container classes that include classes that either present (contains object) or not present (empty). Use java.util.Optional to create an optional class. If the state is not empty, use optional.get to extract the object. In the mentioned example, optional.get extracts the value of the object that has been instantiated before. The optional.else returns the value if the object is present.

2.png

4.Stream API: Stream API processes a collection of objects that involves a process containing a data source, perform intermediate operations, and get a result. The stream API filters a list of employees based on the age and prints all the employees

3.png

Here we can see how using expression-approach oriented is implemented using StreamAPI. The printEmployee function here tracks a list of employees and returns their age and employee data using a simple expression.

How to implement functional programming in Java? To implement functional programming, work on these four techniques:

  • pure functions
  • higher-order functions
  • lazy evaluation
  • closures, and
  • Currying

-> Pure functions are functions that depend on only input parameters and no external state. The external state produces no side effects ie. nothing outside the function is affected (not even the passed parameters). For ex. strlen(), pow(), etc.

4.png In the aforementioned example, we saw how strlen() was evoked for each call, optimizing the for loop, since it was marked pure.

-> Higher-order functions return functions as parameters or returns a functional programming function. The two most common higher-order functions are: filter(): Filter processes a list of elements and returns a list with the elements that return true for the applied condition. map(): Map applies a similar condition to all the elements and returns a list of elements in the same order and doesn’t change the original array. Ex.

5.png In the aforementioned example, collections.sort takes two parameters. The first argument is a list while the second one is a lambda expression. The lambda parameter is what makes it a higher-order expression.

-> Lazy evaluation: In lazy evaluation, the compiler puts the processing or evaluation of an expression on hold until and unless it is needed. It uses memoization as a technique to maintain a dictionary where it can find values of already evaluated variables. For ex.

6.png

Here, interface ‘Supplier’ is a functional interface, where the need of returning a new value every time the interface is evoked, is not necessary. Therefore, it is used as a Lambda expression.

-> Closures: Closures create private variables in functional programming. It allows keeping a reference of the variable even after the block has completed execution. In Java, The lambda expression limits the change of values. Therefore, closures come into the picture and give you access to the outer function from the inner function.

7.png

In a normal scenario, once the execution would have completed, the variable would have been collected by the garbage collector. But by defining a function within a function, the variable scope persists for as long as the function continues to exist. The function salHello()

8.png

-> Currying: Currying allows to pass single arguments for multiple arguments to avoid clutter and reuse the arguments. This means the function takes the first argument at a time, then returns a new function with the second argument, and so on. Ex. this function lets you add two numbers using the currying function.

9.png Currying dissects higher-order functions into a series of functions which returns a function and the last one returns the required value.

Is Java a functional language? Java is not a functional language but imperative. But to tone down certain complexities, with the advent of Java 8, a few aspects of functional programming were added. Also, not all concepts of functional programming solve real problems. Like ‘no side-effect’ is in itself a side-effect at times. It is necessary to differentiate where functional programming is good to use and where not. If needed, the exact example of functional language would be something like Haskell or Clojure which run on all the concepts of functional programming. But Java is indeed solving some greater issues by including a few concepts of functional programming. Want to Become a Full Stack Developer? Learn How.