Lambda expressions for Java

Detailed explanation of lambda expression in Java

Lambda expressions, also known as closures, are the most important new feature that drives the release of Java 8.

Lambda allows functions to be used as parameters of a method (functions are passed into the method as parameters).

Using Lambda expressions can make the code more concise and compact.

Why use Lambda expressions

  • Avoid too many anonymous inner classes
  • It can make the code look more concise
  • Removed a pile of meaningless code, leaving only the core logic

Understanding functional interfaces

  • Understanding the functional interface is the key to learning Lambda expressions
  • Definition of functional interface:
    • Any interface that contains only one abstract method is a functional interface
    • For functional interfaces, we can create objects of the interface through Lambda expressions

grammar

The syntax format of lambda expression is as follows:

(parameters) -> expression
 or
(parameters) ->{ statements; }

The following are important features of lambda expressions:

  • Optional type declaration: there is no need to declare parameter types, and the compiler can uniformly identify parameter values.
  • Optional parameter parentheses: one parameter does not need to define parentheses, but multiple parameters need to define parentheses.
  • Optional curly braces: if the body contains a statement, curly braces are not required.
  • Optional return keyword: if the body has only one expression return value, the compiler will automatically return the value. Braces need to specify that the expression returns a value.

Lambda expression instance

// 1. No parameter is required. The return value is 5  
() -> 5  
  
// 2. Receive a parameter (numeric type) and return twice its value  
x -> 2 * x  
  
// 3. Accept 2 parameters (numbers) and return their difference  
(x, y) -> x – y  
  
// 4. Receive two int integers and return their sum  
(int x, int y) -> x + y  
  
// 5. Accept a string object and print it on the console without returning any value (it looks like returning void)  
(String s) -> System.out.print(s)
public class Java8Tester {
   public static void main(String args[]){
      Java8Tester tester = new Java8Tester();
        
      // Type declaration
      MathOperation addition = (int a, int b) -> a + b;
        
      // No type declaration
      MathOperation subtraction = (a, b) -> a - b;
        
      // Return statement in braces
      MathOperation multiplication = (int a, int b) -> { return a * b; };
        
      // No braces and return statements
      MathOperation division = (int a, int b) -> a / b;
        
      System.out.println("10 + 5 = " + tester.operate(10, 5, addition));
      System.out.println("10 - 5 = " + tester.operate(10, 5, subtraction));
      System.out.println("10 x 5 = " + tester.operate(10, 5, multiplication));
      System.out.println("10 / 5 = " + tester.operate(10, 5, division));
        
      // No parentheses
      GreetingService greetService1 = message ->
      System.out.println("Hello " + message);
        
      // Use parentheses
      GreetingService greetService2 = (message) ->
      System.out.println("Hello " + message);
        
      greetService1.sayMessage("Runoob");
      greetService2.sayMessage("Google");
   }
    
   interface MathOperation {
      int operation(int a, int b);
   }
    
   interface GreetingService {
      void sayMessage(String message);
   }
    
   private int operate(int a, int b, MathOperation mathOperation){
      return mathOperation.operation(a, b);
   }
}

Execute the above script and the output is

10 + 5 = 15
10 - 5 = 5
10 x 5 = 50
10 / 5 = 2
Hello Runoob
Hello Google

You should pay attention to the following two points when using Lambda expressions:

  • Lambda expression is mainly used to define the method type interface executed in the line, for example, a simple method interface. In the above example, we use various types of lambda expressions to define the methods of the MathOperation interface. Then we define the execution of sayMessage.
  • Lambda expressions avoid the trouble of using anonymous methods and give Java simple but powerful functional programming capabilities.

Variable scope

Lambda expressions can only refer to outer local variables marked final, which means that local variables defined outside the domain cannot be modified inside lambda, otherwise compilation errors will occur.

public class Java8Tester {
 
   final static String salutation = "Hello! ";
   
   public static void main(String args[]){
      GreetingService greetService1 = message -> 
      System.out.println(salutation + message);
      greetService1.sayMessage("Runoob");
   }
    
   interface GreetingService {
      void sayMessage(String message);
   }
}

Execute the above script, and the output result is:

Hello! Runoob

We can also access the outer local variables directly in lambda expressions

public class Java8Tester {
    public static void main(String args[]) {
        final int num = 1;
        Converter<Integer, String> s = (param) -> System.out.println(String.valueOf(param + num));
        s.convert(2);  // The output is 3
    }
 
    public interface Converter<T1, T2> {
        void convert(int i);
    }
}

The local variable of lambda expression can not be declared as final, but it must not be modified by the following code (that is, it has implicit final semantics)

int num = 1;  
Converter<Integer, String> s = (param) -> System.out.println(String.valueOf(param + num));
s.convert(2);
num = 5;  
//Error message: local variable num defined in an enclosing scope must be final or effective 
 final

It is not allowed to declare a parameter or local variable with the same name as a local variable in a Lambda expression.

String first = "";  
Comparator<String> comparator = (first, second) -> Integer.compare(first.length(), second.length());  //Compilation will fail 

Keywords: Java Scala

Added by domwells27 on Thu, 14 Oct 2021 08:43:46 +0300