Lambda expressions in Java
A brief introduction to Lambda expression in java
In this topic, we will discuss the lambda expression in java. A lambda expression in Java is an enhanced version of an anonymous class. Therefore first, we will try to understand what we really mean by an anonymous class in Java and then we will drive our focus to the lambda expression.
In Java, an anonymous class can be defined as an inner class without any name. They are basically the nameless nested class in Java. They are used to save our time and make our code more concise. Let us try to understand the implementation of anonymous class with the help of the code blocks given below:
/* Java program to illustrate the standard procedure to override a method declared inside an interface */
/*Declaring an interface named Example with 2 abstract methods show and display*/
interface Example
{
void show();
void display();
}
//Test class implementing the Example interface
class Test implements Example
{
/*Defining the abstract method show inside the implementing class*/
@Override
public void show()
{
System.out.println("Overriding the show method by implementing it inside the test class.");
}
/*Defining the abstract method display inside the implementing class*/
@Override
public void display()
{
System.out.println("Overriding the display method by implementing it inside the test class.");
}
}
//The driver class
class Main
{
public static void main(String[] args)
{
/*Creating an object of Test class and calling the overridden method show and display*/
Test object=new Test();
object.show();
object.display();
}
}
Output-
Microsoft Windows [Version 10.0.22000.318]
(c) Microsoft Corporation. All rights reserved.
C:\Users\USER\Desktop\JTP Folder>javac Main.java //Compile
C:\Users\USER\Desktop\JTP Folder>java Main //Run
Overriding the show method by implementing it inside the test class.
Overriding the display method by implementing it inside the test class.
/* Java program to illustrate how we can override a method declared inside an interface with the help of the anonymous class*/
/*Declaring an interface named Anonymous with 2 abstract methods show and display*/
interface Anonymous
{
void show();
void display();
}
// The driver class
class Main
{
public static void main(String[] args)
{
//Anonymous class implementation
Anonymous object=new Anonymous()
{
/*Defining the abstract method show inside the anonymous class*/
@Override
public void show()
{
System.out.println("Overriding the show method with the help of the anonymous class");
}
/*Defining the abstract method display inside the anonymous class*/
@Override
public void display()
{
System.out.println("Overriding the display method with the help of the anonymous class");
}
};
/*Calling the overridden methods show and display with the help of the object of the anonymous class*/
object.show();
object.display();
}
}
Output-
Microsoft Windows [Version 10.0.22000.318]
(c) Microsoft Corporation. All rights reserved.
C:\Users\USER\Desktop\JTP Folder>javac Main.java //Compile
C:\Users\USER\Desktop\JTP Folder>java Main //Run
Overriding the show method with the help of the anonymous class
Overriding the display method with the help of the anonymous class
As we have already discussed the anonymous class in java, it is a good time to shift our focus towards the lambda expression. Lambda expression is an anonymous function that does not have a name and does not belong to any class. It is an enhanced version of an anonymous class. It provides a transparent and straightforward way to write our code and increases the code readability.
The syntax for the lambda expression is:
parameter -> expression body
The arrow operator was introduced in java through the lambda expression. It divides the code into two parts, that is, the parameters and expression body.
The characteristics of lambda expression are listed below:
- Type declaration is not mandatory in the lambda expression.
- It is not necessary to write the method name while using a lambda expression.
- The parenthesis around parameters is optional.
- We may or may not use the curly braces.
- It is not necessary to use the return keyword with a lambda expression.
The entire concept of lambda expression also revolves around the functional interface. The lambda expression in java only works with the functional interface. Now let us discuss the functional interface in brief.
The functional interface is an interface in java that contains exactly one abstract method. The runnable interface through which we achieve multithreading and the action listener interface, which contains the abstract method action performed, are examples of functional interfaces.
/* Java program to illustrate how we can easily override a method declared inside a functional interface with the help of the lambda expression */
/*Declaring an interface named Anonymous with one abstract methods show and other default method display*/
interface Anonymous
{
void show();
default void display()
{
System.out.println("The non abstract method inside functional interface.");
}
}
// The driver class
class Main
{
public static void main(String[] args)
{
/*
//Anonymous class implementation
Anonymous object=new Anonymous()
{
@Override
public void show()
{
System.out.println("Overriding the show method with the help of the anonymous class");
}
}
*/
//Lambda expression implementation
/*Overriding the abstract method inside the functional interface with the help of lambda expression*/
Anonymous object=()-> System.out.println("Show method is overridden using a lambda expression.");
/*Calling the abstract method show and default method display.*/
object.show();
object.display();
}
}
Output-
Microsoft Windows [Version 10.0.22000.318]
(c) Microsoft Corporation. All rights reserved.
C:\Users\USER\Desktop\JTP Folder>javac Main.java //Compile
C:\Users\USER\Desktop\JTP Folder>java Main //Run
Show method is overridden using a lambda expression.
The non-abstract method inside functional interface.
Why should we use lambda expression?
It is possible to override the abstract methods inside the functional interface by implementing the interface inside a class. We can also use an anonymous class to override the method inside the functional interface but we should use lambda expression because it increases the readability of our code, making it more concise and straight forward.
Lambda parameters:
Parameters can be defined as the values which we can pass through the methods or constructors to influence the behaviour of our program. Just like methods or constructors, the lambda expression can also take parameters. In java 8, it is possible to have zero, one or multiple parametric lambda expressions.
Example:
Zero parametric lambda expression-
()-> System.out.println(“Lamda expression without parameter.”);
One parametric lambda expression-
(param)-> System.out.println(“One parametric Lambda expression ”+param);
Lambda expression with multiple parameters-
(p1, p2)-> System.out.println(“Multiple parametric Lambda expression ”+p1+ “ ”+p2);
/* Java program to illustrate a lambda expression with one parameter*/
/*Declaring a functional interface named CabBook with one abstract method book and other default method display*/
interface CabBook
{
void book(String location);
default void display()
{
System.out.println("The non abstract method inside functional interface.");
}
}
// The driver class
class Main
{
public static void main(String[] args)
{
//Anonymous class implementation
/*
Anonymous object=new Anonymous()
{
@Override
public void show()
{
System.out.println("Overriding the show method with the help of the anonymous class");
}
}
*/
//Lambda expression implementation
/*Overriding the abstract method book inside the interface CabBook*/
CabBook object=(location)-> System.out.println("The cab is booked from "+location);
/*Calling the overridden book method and the default display method*/
object.book("Agartala");
object.display();
}
}
Output-
Microsoft Windows [Version 10.0.22000.318]
(c) Microsoft Corporation. All rights reserved.
C:\Users\USER\Desktop\JTP Folder>javac Main.java //Compile
C:\Users\USER\Desktop\JTP Folder>java Main //Run
The cab is booked from Agartala.
The non abstract method inside functional interface.
/* Java program to illustrate a lambda expression with multiple parameters*/
/*Declaring a functional interface named CabBook with one abstract method book and other default method display*/
interface CabBook
{
void book(String location, String destination);
default void display()
{
System.out.println("The non abstract method inside the functional interface.");
}
}
//The main class
class Main
{
public static void main(String[] args)
{
//Anonymous class implementation
/*
Anonymous object=new Anonymous()
{
@Override
public void show()
{
System.out.println("Overriding the show method with the help of the anonymous class");
}
}
*/
//Anonymous class implementation
/*Overriding the abstract method book using the lambda expression.*/
CabBook object=(location, destination)-> System.out.println("The cab is booked from "+location+"; the final destination is"+destination);
/*Calling the overridden book method and the default method display*/
object.book("Agartala","Bishalgarh");
object.display();
}
}
Output-
Microsoft Windows [Version 10.0.22000.318]
(c) Microsoft Corporation. All rights reserved.
C:\Users\USER\Desktop\JTP Folder>javac Main.java //Compile
C:\Users\USER\Desktop\JTP Folder>java Main //Run
The cab is booked from Agartala; the final destination is Bishalgarh.
The non-abstract method inside the functional interface.
Using return type with the Lambda expression:
The return type of any method can be defined as the type of data returned when a program is executed. For example, if the return type of any method is int data type then it is not possible to return the boolean data type, that is, true or false values.
In this section, we will demonstrate the implementation of return type in java using a lambda expression, with the help of a simple program.
/* Java program to illustrate how we can use lambda expressions with return types in java. */
/*Declaring a functional interface named CabBook with one abstract method book and other default method display*/
interface CabBook
{
double book(String location, String destination);
default void display()
{
System.out.println("The non abstract method inside functional interface.");
}
}
//The main method
class Main
{
public static void main(String[] args)
{
//Anonymous class implementation
/*
Anonymous object=new Anonymous()
{
@Override
public void show()
{
System.out.println("Overriding the show method with the help of the anonymous class");
}
}
*/
//Anonymous class implementation
/*Overriding the abstract method book with the help of lambda expression.*/
CabBook object=(location, destination)->
{
System.out.println("The cab is booked from "+location+", final destination "+destination);
return 5.10;
};
//object.book("Agartala","Bishalgarh");
double fare=object.book("Agartala","Bishalgarh");
System.out.println("The fare shall be: "+fare+" dollars");
object.display();
}
}
Output-
Microsoft Windows [Version 10.0.22000.318]
(c) Microsoft Corporation. All rights reserved.
C:\Users\USER\Desktop\JTP Folder>javac Main.java //Compile
C:\Users\USER\Desktop\JTP Folder>java Main //Run
The cab is booked from Agartala, final destination Bishalgarh
The fare shall be: 5.1 dollars
The non-abstract method inside functional interface.
Accessing local, instance and static variables using a lambda expression:
Variables in java can be defined as the containers which are capable of taking various values like String, int, etc which are essential during the execution of a program.
In this section, we will see how we can access local, instance and static variables using a lambda expression. Before accessing different variables using lambda expression let us briefly discuss the local, instance and static variables in java.
Local variables- These are the variables that we define inside block, methods and constructors. The scope of local variables is lesser than instance variables and static variables.
Instance Variables- These variables are declared outside methods, constructors or blocks but inside any class. The instance variables are non-static. The scope of the instance variable is more than the local variable and less than the static variable.
Static variables- Static variables are declared using the static keyword. These variables are declared within a class but outside. The scope of static variables is more than instance variables and local variables. Static variables belong to the entire class and occupy the same memory for all objects.
/*Java program to demonstrate how we capture variables using lambda expression */
/*Declaring a functional interface named TestInterface with one abstract method show*/
interface TestInterface
{
void show();
}
/*Declaring a class Helper with instance and static variable.*/
class Helper
{
int instanceVar=10; // instance variable
static int staticVar=20; // static variable
}
//The main class
public class Main
{
//show method inside main class
void show()
{
// lambda expression to define show() method
TestInterface testInterface = () -> {
/*accessing of instance variable using lambda expression*/
Helper object=new Helper();
System.out.println("The value of the instance variable is: "+ object.instanceVar);
/*accessing of static variable using lambda expression*/
System.out.println("The value of the static variable is: "+ Helper.staticVar);
/*accessing of local variable using lambda expression*/
int num=30;
System.out.println("The value of the local variable is: "+ num);
};
testInterface.show();
}
//main method
public static void main(String arg[]) {
Main test = new Main();
/*Calling the overidden shown method*/
test.show();
}
}
Output-
Microsoft Windows [Version 10.0.22000.318]
(c) Microsoft Corporation. All rights reserved.
C:\Users\USER\Desktop\JTP Folder>javac Main.java //Compile
C:\Users\USER\Desktop\JTP Folder>java Main //Run
The value of the instance variable is: 10
The value of the static variable is: 20
The value of the local variable is: 30
Method References as Lambda expression:
The concept of method reference was introduced for the first time in Java8. It is a wonderful feature in Java 8 which can be used to refer to the method of the functional interface. We can have reference to the method of the functional interfaces with the help of method reference; also, with the help of method references, our code gets more compact and thus we can say that method references are the easier form of lambda expression in java 8.
In general, when we say method reference, we can have reference to the static method, reference to the parametric methods, we can have reference to the instance method, and we can also have reference to the constructors in java.
Let us discuss the static, instance, parametric method reference and also method reference with constructors in detail:
Static method reference in java 8-
We need to have a functional interface, that is, an interface with only one abstract method. Then we have to write down the class and define the method. We have to make it a static method. We have to make sure that the signature of both the methods is similar; that is, the data type of the arguments taken by the abstract method declared inside the interface and the static method declared in our newly created class should match each other.
Finally, we will use the scope resolution operator, which will automatically map the static method declared inside the class with the abstract method inside an interface.
Code skeleton for static method reference-
//The interface
interface I1
{
/*An abstract method, say m1, with two int data types as the parameter*/
}
//The class
class C1
{
/*An instance method, say m2, accepting two int data types as parameter*/
}
//The driver class
public class Main
{
//Main method.
/*Creating an object */
/*Creating a reference of the I1 interface and mapping methods m1 and m2 with the help of the scope resolution operator.*/
/*Finally we call m1, which implements the m2 method and prints or return the result*/
}
Instance method reference in java 8-
We can have instance method reference. These are the methods with respect to the object of the class. We need to create an object of the class, and for the reference variable of the object, we need to provide a method reference.
Code skeleton for an instance method reference-
//The interface
interface I1
{
/*An abstract method, say m1, with two int data types as the parameter*/
}
//The class
class C1
{
/*A non static method, say m2, accepting two int data types as parameter*/
}
//The driver class
public class Main
{
//Main method.
/*Creating an object of the class*/
/*Creating a reference of the I1 interface and mapping methods m1 and m2 with the help of the scope resolution operator and the object.*/
/*Finally, we call m1, which implements the m2 method and prints or return the result*/
}
Method reference with the constructor in java 8:
Lastly, if we want to have a method reference with the constructor then we need to use the new operator with the scope resolution operator.
Code skeleton for method reference with constructor-
//The interface
interface I1
{
/*An abstract method, say m1, with two int data types as the parameter*/
}
//The class
class C1
{
/*A constructor of class c1 is declared. It takes the same arguments as the abstract method inside the interface.*/
}
//The driver class
public class Main
{
//Main method.
/*Creating a reference of the I1 interface and mapping methods m1 with the constructor of class c1 with the help of the scope resolution operator and the new keyword.*/
/*Finally, we call m1, which implements the code defined inside the constructor and prints or return the result*/
}
Let us take a couple of programming examples to show that how we can come up with the method references in Java 8 using the lambda expression:
/*A java program to illustrate the static method reference in java 8*/
/*Declared a functional interface Calculator with an abstract method add*/
interface Calculator
{
void add(int num1, int num2);
}
/*Declaring a class and defining a static method sum. We should make sure that the signature of the method add and the method sum are the same*/
class Calculate
{
public static void sum(int n1, int n2)
{
System.out.println("The sum of "+n1+" and "+n2+" is "+(n1+n2));
}
}
//Main class
public class Main
{
public static void main(String[] args)
{
//calculate.sum(10,20);//The sum of 10 and 20 is 30
//Referance to a static method
Calculator ref=Calculate::sum;
ref.add(10,20);
}
}
Output-
Microsoft Windows [Version 10.0.22000.318]
(c) Microsoft Corporation. All rights reserved.
C:\Users\USER\Desktop\JTP Folder>javac Main.java //Compile
C:\Users\USER\Desktop\JTP Folder>java Main //Run
The sum of 10 and 20 is 30
/*A java program to illustrate the instance method reference in java 8*/
/*Declared a functional interface Calculator with an abstract method add*/
interface Calculator
{
void add(int num1, int num2);
}
/*Declaring a class and defining instance method sum. We should make sure that the signature of the method add and sum are the same*/
class Calculate
{
public void sum(int n1,int n2)
{
System.out.println("The sum of "+n1+" and "+n2+" is "+(n1+n2));
}
}
//Main class
public class Main
{
public static void main(String[] args)
{
//calculate.sum(10,20);//The sum of 10 and 20 is 30
//Referance to a instance method
Calculate obj=new Calculate();
Calculator ref=obj::sum;
ref.add(20,30);
}
}
Output-
Microsoft Windows [Version 10.0.22000.318]
(c) Microsoft Corporation. All rights reserved.
C:\Users\USER\Desktop\JTP Folder>javac Main.java //Compile
C:\Users\USER\Desktop\JTP Folder>java Main //Run
The sum of 20 and 30 is 50
/*A java program to illustrate the method reference with the constructors in java 8*/
/*Declared a functional interface Messenger with an abstract method getMessage*/
interface Messenger
{
void getMessage(String msg);
}
/*Declaring a class Message with a parameterised constructor that
takes the string data type as an argument. We should make sure that the signature of the method getMessage and the constructor of the Message class are the same*/
class Message
{
Message(String msg)
{
System.out.println("The secret message for you is: "+msg);
}
}
//The main class
public class Main
{
public static void main(String[] args)
{
//Method reference with the constructor.
Messenger ref=Message::new;
ref.getMessage("May God bless you. Keep rocking in 2022.");
}
}
Output-
Microsoft Windows [Version 10.0.22000.318]
(c) Microsoft Corporation. All rights reserved.
C:\Users\USER\Desktop\JTP Folder>javac Main.java //Compile
C:\Users\USER\Desktop\JTP Folder>java Main //Run
The secret message for you is: May God bless you. Keep rocking in 2022.
Conclusion:
In this topic, we have discussed all the prerequisites, that is, anonymous class, functional interface and other essentials required for having a good understanding of Lambda expression. Then we have deep dived into the lambda expression with a couple of coding examples. We have also discussed the perks of using lambda expression over implementing class and anonymous class. Finally, we have signed off discussing the method reference in java 8, taking suitable java programs as examples.