What is Lambda expression
Suppose you have an interface which contains declaration of a method. Now, in order to define this method and call it, what steps will you take :
- Create a class which implements this interface.
- Define the interface method in the class (provide it a body).
- Create an object of this class and call the implemented method using this object.
With Lambda expressions, you do not need to take any of the steps to define an interface method except to define its body or what the method will do.
In addition, this method will not even have any name, it will be an anonymous method.
Lambda expression is the most important and the biggest out of java 8 features.
We will understand in detail about how to define a Lambda expression in this post and where is it suitable.
Based on all the discussion till now, a Lambda expression can be summarized as:
Functional interfaces in java 8
In above section, it was mentioned that Lambda expression is a definition(or body) of a java method declared in an interface.
But, for an interface method to be eligible for conversion to a Lambda expression, the interface should be a Functional Interface.
A Functional interface is an interface with ONLY ONE abstract method. Thus, any interface which has only one method declaration is a Functional Interface.
These methods should be preceded with
default
keyword and such methods are called default interface methods.A Functional Interface is annotated with @FunctionalInterface
annotation. This is not mandatory but provides a compile time check.
Lambda expression & Functional interface relation
It should be clear till here that a Lambda expression represents a method definition and this method should belong to a Functional Interface.
Now the question arises,
How are Lambda expression and Functional Interface related to each other ?
Suppose you have a method M1 which takes an interface type as argument.
Prior to java 8, you need to pass an object of a class which implements this interface to M1 or provide interface method definition at the place where you are calling M1.
For Example, consider java.lang.Thread
class. It has a constructor which expects an object of type java.lang.Runnable
(an interface) as argument.
We can create an object of Thread as:
1. new Thread(an object of class which implements Runnable) Or
2. provide method definition at the required place
new Thread(new Runnable() {
public void run(){
System.out.print(“New Thread”);
}
});
Above pieces of code when written using Lambda expression will look like
new Thread(
() -> { System.out.print(“New Thread”); } // Lambda expression
);
Cleaner isn’t it !!
Don’t worry about the syntax. We shall go into that too.
For now, understand that a Lambda expression can only be used at a place where there is a requirement of Functional Interface.
It is an implementation of the method defined in the Functional Interface.
Lambda expression syntax
A Lambda expression is constituted of three parts:
- Optional Parameters : This depends on the parameters of the interface method which is represented by Lambda. Parameters can be zero, one or more.
- Arrow or Lambda operator : ->
- Body : Implementation of method. It can have zero or more statements.
Note the following points when defining a Lambda expression:
- When there is only one parameter, there is no need of parenthesis.
- Body of a Lambda expression can have zero, one or more statements.
- When there is only one statement in the Lambda expression, there is no need of brackets around the body part.
- Parameters of Lambda expression can have type associated with them or they can be defined without type.In this case, their type is determined from the context where the expression is used.
Example, suppose there is a method defined in an interface which accepts 2 integer arguments and returns their product.
A Lambda expression for this method can be written as(int x, int y) -> { return x * y; }
.
Same can also be written as(x, y) -> { return x * y; }
.
In the second case, their type is determined from the method declaration of the interface.
Below is a list of examples of Lambda expressions having different parameters and statements.
1. without arguments and 1 statement
() -> System.out.print(“No arg Lambda”);
—————————————————————————————-
2. without arguments & statements > 1
() -> {
System.out.print(“Multi Line Lambda : Line 1”);
System.out.print(“Multi Line Lambda : Line 2”);
}
—————————————————————————————-
3. single argument with type and 1 statement
(int x) -> System.out.print(x);
—————————————————————————————-
4. single argument without type and 1 statement
(x) -> System.out.print(x);
—————————————————————————————-
5. single argument without type(parenthesis omitted) & 1 statement
x -> System.out.print(x);
—————————————————————————————-
6. multiple arguments with type and 1 statement
(int x, int y) -> System.out.print(x);
—————————————————————————————-
7. multiple arguments without type and 1 statement
(x, y) -> System.out.print(x);
—————————————————————————————-
8. single argument with a return statement
(x) -> return x+2;
Lambda expression examples
By now, you must have understood the meaning and syntax of Lambda expressions.
Below are listed various real usage examples of Lambdas along with explanation
- Create Runnable Object and Pass it to Thread
new Thread (
() -> System.out.println(“Runnable as Lambda”);
)java.lang.Runnable
is a Functional Interface and its run method takes no arguments and returns nothing.
Hence it can be represented using a Lambda expression as () -> { // statements } where empty parenthesis represent no arguments. - Binding an event to a Swing component
JButton button = new JButton(“Lambda Demo”);
button.addActionListener(
(event) -> { System.out.println(“Declared as Lambda”); }
);addActionListener()
method takes an argument of typejava.awt.ActionListener
which has only 1 methodactionPerformed()
, hence it can be represented as a Lambda expression.
This method takes an event object and returns nothing.
Thus, its Lambda expression has 1 argument and a print statement. - When using Comparator or Comparable to sort a list
ArrayList<String> list = new ArrayList<>();
Collections.sort(list, (o1, o2) -> {
return o1.compareTo(o2);
});A list can be sorted using sort method of
java.util.Collections
class. This method takes a list to sort and an object of typejava.util.Comparator
.Nowjava.util.Comparator
is a Functional interface with a method compare, hence it can be represented as a Lambda expression.
This method takes 2 arguments and returns an int. Thus, its Lambda expression has 2 arguments and is returning an integer.
Remember that Lambda expression is not bound to any method or interface.
This means that same Lambda can be used to represent different method definitions.
Example,
below Lambda takes 1 argument and returns nothing.
x -> System.out.print(x);
Same Lambda can be used for multiple functional interfaces all of which have a method which takes 1 argument and does not return anything.
Lambda expressions as Objects
A Lambda expression can be assigned to a variable of an interface type which matches its definition.
Thus the following assignment is perfectly valid.
java.util.Comparator<String> cmp = (o1, o2) -> { return o1.compareTo(o2); };
Then you can pass the above variable at any place where an object of type java.util.Comparator
is expected.
Also, same Lambda expression can be assigned to any interface type whose method signature matches with the interface method.
Let’s tweak in
- A Lambda expression can represent only methods of an interface.
- A method represented by Lambda expression should be the only method in the interface.
- Names of parameters of a Lambda expression can be anything.
They need not match the parameter names matching the actual method arguments. - Every interface which has a single method is a Functional Interface.
It is not necessary that it is annotated with@FunctionalInterface
annotation.
For any doubts related to Lambda expression or to report any typos/errors, feel free to use the comment box below.