Java 8 Lambda Expressions

Lambda expressions, also known as closures, are the most important new features that drive the release of Java 8.
Lambda allows functions to be parameters of a method (functions are passed as arguments into methods).
Using Lambda expressions can make the code more compact and compact.

grammar

The syntax of a lambda expression is as follows:
( parameters ) -> expression or ( parameters ) -> { statements ; }
The following are the important features of lambda expressions:
  • Optional type declaration: No need to declare the parameter type, the compiler can identify the parameter value uniformly.
  • Optional parameter parentheses: One parameter does not need to define parentheses, but multiple parameters need to define parentheses.
  • Optional braces: If the body contains a statement, braces are not needed.
  • Optional return keyword: If the body has only one expression return value then the compiler will automatically return the value, curly braces need to specify that the explicit expression returns a numeric value.

Lambda expression example

Enter the following code in the Java8Tester.java file:

Java8Tester.java file

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 statements 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)); // Without parentheses GreetingService greetService1 = message -> System.out.println("Hello " + message); // use parentheses GreetingService greetService2 = (message) -> System.out.println("Hello " + message); greetService1.sayMessage("Bubble"); 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, the output is:
$ javac Java8Tester.java 
$ java Java8Tester
10 + 5 = 15
10 - 5 = 5
10 x 5 = 50
10 / 5 = 2
Hello Bubble
Hello Google
There are two things to note when using Lambda expressions:
  • Lambda expressions are mainly used to define method type interfaces that are executed inline, 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 implementation of sayMessage.
  • Lambda expressions eliminate the hassle of using anonymous methods and give Java simple but powerful functional programming capabilities.

Variable scope

Lambda expressions can only reference outer local variables marked final, which means that local variables defined outside the domain cannot be modified inside the lambda, otherwise compilation errors will occur.
Enter the following code in the Java8Tester.java file:

Java8Tester.java file

public class Java8Tester { final static String salutation = "Hello! "; public static void main(String args[]){ GreetingService greetService1 = message -> System.out.println(salutation + message); greetService1.sayMessage("Bubble"); } interface GreetingService { void sayMessage(String message); }
}
Execute the above script, the output is:
$ javac Java8Tester.java 
$ java Java8Tester
Hello! Bubble
We can also access the outer local variables directly in lambda expressions:

Java8Tester.java file

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); } }
Local variables of lambda expressions may not be declared as final, but must not be modified by subsequent code (that is, implicitly have 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 effectively  final
It is not allowed to declare a parameter or a 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());  //compile error      

Comments