With the release of Java 8, lambda expressions were introduced. Lambda expressions are anonymous implementations of an interface containing a single abstract method. Below, I will discuss the benefits of functional programming using lambda expressions and take you through a simple example to help display the power in utilizing lambda expressions in Java.
What are Lambda Expressions?
As mentioned above, lambda expressions are anonymous implementations of interfaces containing a single abstract method. This type of interface is known as a functional interface. In previous versions of Java, you would need to either create a new Java class implementing such an interface or implement the interface through the use of an anonymous inner class. With lambda expressions, however, you can cleanly develop an implementation of a functional interface with fewer lines of code, and without tying the implementation to an identifier.
In fact, with lambda expressions, you could both implement a functional interface and pass this functionality to another method, allowing that method to leverage the implementation. Let’s get into an example doing just that.
Using Lambda Expressions in Java 8
Creating a Functional Interface
The first step in our example is to create a functional interface for us to utilize in our lambda expression example. A functional interface is an interface with exactly one abstract method. In Figure 1, you can see the code for the interface MathematicalOperation.
This interface has a single abstract method with the method name calculate. The calculate method takes one parameter of type int and returns an int value. The idea behind this example is to use lambda expressions to define the functionality of the calculate method. In this way we can take an int value and perform some mathematical operation on it to return another value.
@FunctionalInterface public interface MathematicalOperation { abstract int calculate(int x); }
One final note in MathematicalOperation is the annotation @FunctionalInterface applied to the interface itself. This will enforce the fact that the interface must contain only a single abstract method.
Implementing Interfaces with Lambda Expressions
The next step is to create the class LambdaExample. Within this class, we will use lambda expressions to implement three versions of the abstract method calculate(int) from the interface MathematicalOperation.
The class LambdaExample contains two methods. The first method executeLambda has two parameters. The first is the int value to be utilized within the calculate method, but the important parameter to note here is the second argument.
The second argument is of the type MathematicalOperation. Essentially, we will pass our lambda expression as an argument to our executeLambda method. Finally, the purpose of executeLambda will be to call the calculate method defined by our lambda expression. We will pass the first argument to the calculate method, thus performing a mathematical operation on the first argument and printing the resulting value to the console.
public class LambdaExample { public static void executeLambda(int val, MathematicalOperation oper) { System.out.println("value: " + oper.calculate(val)); } public static void main(String[] args) { int val = 5; executeLambda(val, (x) -> x*x); executeLambda(val, (x) -> x-5); executeLambda(val, (x) -> 2*x); } }
Now let’s get to writing our actual lambda expressions! In the main method of our LambdaExample class, we initialize the int variable ‘val’ to the value of 5. The next three lines are calls to the executeLambda method. The int variable we just initialized will be the first argument passed to executeLambda. What we want to focus on, however, is the second argument. In each of the calls to executeLambda we are passing a lambda expression, implementing the MathematicalOperation interface, as the second argument.
The format for the lambda expression is as follows:
(parameters) -> functionality
The first lambda expression implements the MathematicalOperation interface as follows:
(x) -> x*x
This means that the calculate method takes an int value ‘x’ and returns that value multiplied by itself. The other two implementations perform a different mathematical operation on the value passed as the parameter. Please see the code above as a reference for the other implementations.
The true power of lambda expressions isn’t in the problem that we solved here, but how we solved it. Rather than having to implement the functional interface by creating three separate Java classes to define such functionality or writing three anonymous inner classes, we simply enclose the parameter for the single abstract method within parentheses and use the arrow operator to indicate that the functionality is to follow. In doing this, we wrote one line of code that defines the operation to be performed on the parameter, which results in the value to be returned. Please see Figure 3 for the results of the main methods execution.
Fig 3. Results from LambdaExample main method
Conclusion
Lambda expressions are a form of functional programming allowing for an anonymous implementation of a functional interface. Lambda expressions have the benefit of resulting in fewer lines of code than the traditional implementation of an interface which was done through the creation of a new class or the use of an anonymous inner class. These expressions allow the developer to write cleaner code that is easier to maintain.