Java 8 Lambda Expressions Tutorial with Examples

Lambda Expressions are Java’s answer to the functional programming concept of closures. Well… almost!! Lets deep dive into the concept of lambda expressions now starting with the definition of lambdas. This will be followed by understanding the structure of lambda expressions and their ‘relationship’ with their counterpart functional interfaces. We will then take a look at an example showing how lambdas are used to pass different behaviors as parameters.

What are Lambda Expressions
A Lambda Expression ( or just a lambda for brevity) is a representation of an anonymous function which can be passed around as a parameter thus achieving behavior parameterization. A lambda consists of a list of parameters, a body, a return type and a list of exceptions which can be thrown. I.e. it is very much a function, just anonymous.

An instance of a lambda can be assigned to any functional interface
Read – Java 8 Functional Interface tutorial
whose single abstract method’s definition matches the definition of the lambda. In fact, a lambda is a less verbose way of defining an instance of an interface provided the interface is functional. Since, the definition of a lambda can match the definition of multiple functional interfaces, hence, a lambda instance can be assigned to any of these matching interfaces.

Understanding Lambda Expressions
Let us now take a look at an example of a lambda expression. To understand the usage of lambda expressions from the ground up, we will first have to first define a functional interface.

Defining a functional interface for which lambda will be created
package com.javabrahman.java8;
@FunctionalInterface
public interface FirstInterface {
 //the abstract method	
 public void singleMethod(String param);
}

Lambda equivalent for the above functional interface would look like

(String param)->{System.out.println("My lambda says "+param);};

Important points to understand regarding the lambda expression defined above-

  1. The element to the left of the arrow(->) are the parameters of the lambda. In this case the input parameter is defined as- String param.
  2. To the right of the arrow(->) we have the body of the lambda. Body is where the actual processing within a lambda happens. I.e. the logic of the lambda goes here. The above lambda has a simple logic. It prints the param passed to it appended to a general string value and does not return anything, i.e. return type is void (more on returning values later).
  3. Parameter – String param, and return type – void, both closely match the signature of singleMethod() in FirstInterface defined above. This matching of signatures allows us to assign an instance of the lambda defined above to an instance of the interface FirstInterface as shown below –
FirstInterface instance = (String param) -> {System.out.println("My lambda says "+ param);};
We can now pass this instance as a parameter wherever FirstInterface is expected.

Understanding Lambda return types
Lambda syntax contains 2 variants of return types. This types are based on the contents in lambda following the arrow(->) sign –
Variant 1.(parameters) -> expression– In this variant the return type of the lambda expression will be same as the resultant type of the expression
Variant 2.(parameters) -> {statements;} – In this variant, there will be no return type(or void return type) unless the statements inside the curly braces explicitly return something at the end. In that case the return type will be same as the type of the variable returned.

Lambda Expressions in Practice
Having covered the basics of lambda, its now time for us to see how to use lambda expressions in a program.

Let us extend the above example to illustrate the usage of lambdas. We have already defined an instance of the above lambda as –
FirstInterface instance=(String param)->{System.out.println("My lambda says "+param);};

Lets say there is a class FirstInterfacePrinter which uses an instance of type FirstInstance to print a value. The FirstInterfacePrinter class is defined as follows –

FirstInterfacePrinter.java
package com.javabrahman.java8;
public class FirstInterfacePrinter {
	
 public void print(FirstInterface firstInterface){
  firstInterface.singleMethod("apple");
 }

 public static void main(String args[]){
  FirstInterfacePrinter printer=new FirstInterfacePrinter();
  <span class="jb-highlight-lightblue">printer.print((String param) -> {System.out.println("My lambda says "+ param);});</span>
 }
}
 OUTPUT of the above code
My lambda says apple

Now lets change the printing behavior a bit. Lets say now we want to print a little differently with the following definition of the lambda expression-
FirstInterface secondInstance=(String param)->{System.out.println("My lambda's parameter value is "+ param);};

The main method of FirstInterfacePrinter now looks like this –

FirstInterfacePrinter's main() method
public static void main(String args[]){
 FirstInterfacePrinter printer=new FirstInterfacePrinter();
 printer.print((String param) -> {System.out.println("My lambda's parameter value is "+ param);});
}
 OUTPUT of the above code
My lambda’s parameter value is apple

As you can see the print function of FirstInterfacePrinter printed differently based on the lambda passed to it. In other words, using lambda expressions we could create 2 different and anonymous implementations of FirstInterface by simply defining the logic as a lambda.

Lambdas and Behavior Parameterization
If you observe closely, behavior of printing was passed as a part of the lambda expression to the print function. This is an example of behavior parameterization – passing of behavior as a parameter. In fact, lambdas are the main instruments of enabling behavior parameterization in Java 8.

Summary
In this fundamental tutorial on lambda expressions in Java 8 we understood the definition, structure, and usage of lambda expressions. We also understood how lambdas help us in achieving behavior parameterization.

 

Digiprove sealCopyright © 2014-2017 JavaBrahman.com, all rights reserved.