Tech Master Tutorials
Email Facebook Google LinkedIn Pinterest Twitter
Home Java Java 8 Java Interview Questions Java8 Interview Questions Object Oriented Programming in Java JVM Java Programming

Lambda Expressions

Lambda expressions enable us to pass the functionality as a method argument.
Let’s have a look at the below example of creating a thread using an anonymous inner class.

public class AnonymousClassTest {

	public static void main(String[] args) {
		Thread thread = new Thread(new Runnable() {
			@Override
			public void run() {
				System.out.println("Running in thread = "+Thread.currentThread().getName());
			}
		});
		
		thread.start();
	}
	
}
In the above example, we are creating an anonymous class where we are defining the functionality for the run method.
We create some unnecessary and bad looking code when we create an anonymous class.

We already know that Runnable interface got only one abstract method that is the run () method.
This makes the Runnable interface a Functional Interface.
So instead of creating anonymous class (or creating a Runnable class), can we have some capability using which we can
pass functionality or code as data to the Thread class, and program will understand that we are passing the implementation code
for run() method of Runnable.
We have lambda for that. But we can use lambda only when interface has a single abstract method
(When we have Functional Interface).

Interfaces that consist of only one abstract method are called functional interfaces.
We can use lambda expression to pass the functionality only where you are expecting a functional interface type
Wherever we expect Runnable as argument in a method, we can pass lambda expression instead of
anonymous class (or defining a Runnable) and then passing it to a Thread class.
Instead of creating an anonymous inner class, we can pass a Lambda expression for the same


Creating a Thread using Lambda:
public class LambdaTest {

	public static void main(String[] args) {
		
		Thread thread = 
		new Thread(() -> System.out.println("Running in thread = "+Thread.currentThread().getName()));
		
		thread.start();
	}

}


Capabilities of lambda expressions:

  • Enable Functional Programming :
    You can define a functional interface and can pass a lambda expression as a functionality wherever
    you are expecting that functionality.
    You do not need to create a class and implement the interface to define the functionality.
    As in case when we create a thread using a Runnable, we had two choices prior to lambda.

    Either create a class implementing Runnable and provide the task functionality definition inside the run() method.
    And then initialized a Thread object by passing the implemented class object.
    OR
    Create an anonymous class for the Runnable that we had created in an earlier example of anonymous class.

    In both case you have to write some unnecessary code. Creating extra class just to provide the runnable implementation
    adds number of lines of code.
    Even creating an anonymous class make the code look unreadable.
    Instead you can just pass one or few lines of lambda expression that make the code look really clean and readable.
  • Compact and readable code.
  • Interface with a single method, can expressed more easily, no need to create a class/anonymous class.




Syntax :
  • A Lambda expression contains comma-separated list of formal parameters enclosed in parentheses.
    Data type of the parameters is optional in a lambda expression. Even you can omit the parentheses
    in case of one parameter.
    Zero/No parameter case :
                    () -> System.out.println("Hello World !")
                    OR
                    () -> doSomething()
    One parameter case :
                    parameter -> System.out.println(parameter)
    Passing multiple parameters with parenthesis :
                    (param1,param2) -> param1+param2
  • Contains arrow token :
                    ->
  • A body, which consists of a single expression or a statement block.

    (param1,param2) -> param1+param2
    Or
    (param1,param2) -> {
    param1+param2;
    }
    Or
    (param1,param2) -> {
    return param1+param2;
    }
  • A body, which consists of multiple statements, in that case statements are written inside curly braces.

    (param1,param2) -> {
    param3 = param1+param2;
    return param3;
    }
  • In case of a single expression, Java runtime evaluates the expression and then returns the value.
    Alternatively, return statement can be used to return the value.
    Even if you do not want to return any value that is also acceptable.
    For example operation like printing the value on console.

    displayMessage -> System.out.println(displayMessage)

    Note that a lambda expression looks a lot like a method declaration;
    you can consider lambda expressions as anonymous methods—methods without a name.




Find the following examples that depicts the use cases of lambda expressions.
  • In the following example defining a Lambda Expression corresponding to the functional interface
    IntegerOperation. At the same time anonymous inner class could be used for implementation of the
    functional interface. But using the Lambda expression makes the code more compact and easy.

    	public class LambdaExpressionOperationTest {
    	  
    		/*Functional Interface which contains an abstract method operation with two parameters*/ 
    	    interface IntegerOperation {
    	        int operation(int a, int b);   
    	    }
    	  
    	    /*A method which receives two parameters along with a functional interface reference which 
    	    in turn perform some operation*/
    	    public int performBinaryOperation(int a, int b, IntegerOperation iop) {
    	        return iop.operation(a, b);
    	    }
    	 
    	    public static void main(String... args) {
    	    
    	        LambdaExpressionOperationTest obj = new LambdaExpressionOperationTest();
    	        
    	        /*Instance of IntegerOperation which contains a Lambda Expression*/
    	        IntegerOperation addition = (a, b) -> a + b;
    	        
    	        /*Instance of IntegerOperation which contains a Lambda Expression*/
    	        IntegerOperation subtraction = (a, b) -> a - b;
    	        
    	        System.out.println("2 + 2 = " +
    	        		obj.performBinaryOperation(2, 2, addition));
    	        System.out.println("12 - 2 = " +
    	        		obj.performBinaryOperation(12, 2, subtraction));    
    	    }
    	}
    	
    	Output :
    	
    	2 + 2 = 4
    	12 - 2 = 10
    	
  • Using the Lambda Expression for the forEach() method provided in the collections classes in the Java8 version.
    Passing functional interface instance defined using Lambda Expressions.
    	package LambdaExpression;
    	
    	import java.util.HashSet;
    	
    	public class LambdaTestInterator {
    	
    		
    		
    		public static void main(String[] args) {
    		
    			HashSet intSet=new HashSet<>();
    			
    			intSet.add(1);
    			intSet.add(2);
    			intSet.add(3);
    	
    			/*Passing a Lambda Expression for Consumer functional 
    			interface defined in java.util.function package. As forEach method defined for 
    			collection classes receives the Consumer reference, a lambda expression is
    			being passed for the Consumer functional interface
            	
    			
    			/*Without any parenthesis and curly braces*/
    			intSet.forEach(intVal -> System.out.println(intVal));
    			
    			/*Passign the variable with parenthesis*/
    			intSet.forEach((intVal) -> System.out.println(intVal));
    			
    			/*Passing parameter with parenthesis and expression with curly braces*/
    			intSet.forEach((intVal) -> {
    										System.out.println(intVal);
    									   });
    			
    			
    		}
    		
    		
    	}