In Part 1 of this article, we had taken a look at functional interfaces. We had seen how functional interfaces along with lambda expressions help to make Java code shorter. In this article, we will be taking a closer look at lambda expressions, understand what they are, and learn the different ways of using them.
- What are lambda expressions
- Lambda expression Syntax
- How to use lambda expressions
- Lambda Expression Examples
- Why should you use Lambda Expressions?
What are lambda expressions
A lambda expression is just like a method. So, it can accept any parameters and return any value. However, unlike other methods, it does not have a method name. It is used to implement the abstract method within a functional interface. Since a lambda expression is a method without a method name, it is also known as an anonymous function.
Lambda expression Syntax
A lambda expression has the following syntax:
(parameters) -> lambda body;
Parameters
Parameters are the values passed into the lambda expression. The lambda expression can accept zero or more parameters. Parameters need to be specified in parentheses. If the lambda expression does not accept any parameters, an empty parenthesis needs to be specified. If the lambda expression accepts a single parameter, the parentheses may be skipped. The data type of the parameters is optional, if it is not specified, it is inferred based on the value passed in. If there are multiple parameters, then they need to be separated by commas.
Lambda operator
-> is known as the lambda operator.
Body of the lambda expression
Any code placed in curly brackets after the lambda operator constitutes the body of the lambda expression. If there is a single statement in the body, the curly brackets can be skipped. If the lambda expression returns a value, the return keyword may be used, but again it is optional and may be skipped if the body of the lambda expression consists of a single statement.
How to use lambda expressions
As mentioned earlier, a lambda expression is used in conjunction with a functional interface to implement the abstract method within a functional interface.
Sample Code
@FunctionalInterface public interface Reader { public void read(); }
- This code defines a functional interface called Reader
- Line 3 specifies an abstract method called read
public class ReaderDemo { public static void main(String[] args) { Reader excelReader = () -> System.out.println("Reading Excel File"); excelReader.read(); } }
- This code defines a class called ReaderDemo.
- Line 3 defines a Reader instance called excelReader and assigns it a lambda expression.
- This means that the specified lambda expression will be used to implement the read method in the Reader interface.
- Since the read method does not accept any parameters, empty parentheses are specified and the lambda expression body consists of a single System.out.println statement
- Line 4 invokes the read method. This causes the code within the lambda expression to be executed.
Output
Reading Excel File
Lambda Expression Examples
Let us now take a look at some different examples of lambda expressions.
Single Parameter, No Return Value
The following code demonstrates a lambda expression that accepts a single parameter and does not return any value.
@FunctionalInterface public interface Operator { public void operate(int num); }
- This code specifies a functional interface called Operator with an abstract method called operate
- operate method accepts an int parameter and returns a void
public class OperatorDemo { public static void main(String[] args) { Operator op = num -> System.out.println("Increasing num by 2:"+(num+2)); op.operate(10); } }
- This code specifies a class called OperatorDemo
- Line 3 uses a lambda expression to implement the operate method in Operator. Since operate accepts a single parameter, the lambda expression also accepts a single parameter called num.
- The body of the lambda expression consists of a System.out.println statement that increments the input value by 2 and prints it.
Line 4 invokes the operate method with the value 10. This causes the code within the lambda expression to be executed.
Output
Increasing num by 2:12
Multiple Parameters and Return Value
The following code demonstrates a lambda expression that accepts two parameters and returns a value
@FunctionalInterface public interface Operator { public int operate(int num1,int num2); }
- As before, this code specifies a functional interface called Operator with an abstract method called operate
- The operate method accepts two int parameters and returns an int result
public class OperatorDemo { public static void main(String[] args) { Operator op = (num1,num2) -> num1+num2; int sum = op.operate(10,20); System.out.println("sum:"+sum); } }
- This code specifies a class called OperatorDemo
- Line 3 uses a lambda expression to implement the operate method in Operator. Since operate accepts two parameters, the lambda expression also accepts two parameters called num1 and num2. Note that they are specified in parentheses
- The body of the lambda expression simply adds the two input numbers and returns the result. Note that the return keyword is not explicitly specified, since the lambda expression body consists of a single statement, it is implied
- Line 4 invokes the operate method with the values 10 and 20. This causes the code within the lambda expression to be executed.
Output
Why should you use Lambda Expressions?
In addition to making the code concise and easier to read, Lambda expression have several benefits which make using them very beneficial
Providing Different Implementations at Runtime
Lambda expressions allow providing different implementations for the same functional interface method at runtime.
Sample Code
@FunctionalInterface public interface Operator { public int operate(int num1,int num2); }
As before, this code specifies a functional interface called Operator with an abstract method called operate that accepts two int arguments and returns an int result
public class OperatorDemo { public static void main(String[] args) { Operator op = (num1,num2) -> num1+num2; int sum = op.operate(10,20); System.out.println("sum:"+sum); Operator op2 = (num1,num2) -> num1-num2; int difference = op2.operate(25, 10); System.out.println("Difference:"+difference); } }
- This code specifies a class called OperatorDemo
- Line 3 declares an Operator instance called op and implements it using a lambda expression that adds the input numbers and returns the result
Line 7 declares an Operator instance called op2 and implements it using a lambda expression that subtracts num2 from num1 and returns the result - So the same functional interface that is Operator is implemented using different lambda expressions, one causes the input arguments to be added while the other causes the input arguments to be subtracted
Output
sum:30
Difference:15
For-each Support
Java 8 has added a new method called forEach to all the Collection interfaces. This allows iterating internally over a Collection without having to write an explicit for loop. The forEach method accepts as a parameter a Consumer instance which is an in-built functional interface and can be implemented via a lambda expression.
Sample Code
Set languages = Set.of("Java","Ruby","Python","C"); languages.forEach(language -> System.out.println("language is:"+language));
- Line 1 declares and initializes a new Set called languages
- Line 2 invokes the forEach method on languages with a lambda expression corresponding to the Consumer interface
Output
language is:Java
language is:Ruby
language is:Python
language is:C
Conclusion
So, in this article, we understand what lambda expressions are. We took a close look at the syntax of lambda expressions. We saw some examples of lambda expressions. Finally, we saw some of the benefits of lambda expressions.