Lambda in Java
--
I advise reading the behavior parameterization before moving further.
Let’s take a quick context from behavior parameterization:
Problem:
You want to sort a list of phones based on the price.
Solution:
Collections class provides a generic interface you can pass a list of records and your sorting strategy. (Eventually, it is using strategy design pattern)
You can pass the behavior via an anonymous class as below
Comparator<Phone> comparator = new Comparator<Phone>() {
@Override
public int compare(Phone ph1, Phone ph2) {
return ph1.getPrice().compareTo(ph2.getPrice());
}
};Collections.sort(phones, comparator);
The actual requirement was to just pass the behavior (method) of sorting but in an earlier version of java, we had to wrap the behavior in the class. It was not encouraging and this problem is solved with a lambda expression.
Lambda Expression
Lambda expression is a succinct illustration of an anonymous function.
Lambda expression is a function that is not associated with any class and doesn’t have a name. It can be passed as an argument. Also, it prevents us from writing a boilerplate code which we generally write during anonymous class.
Note
Technically lambda is not allowing you to do anything new that you can’t do before java 8. But using lambda, you don’t need to write anonymous classes to utilize the behavior parameterization.
Before Java 8:
Comparator<Phone> comparator = new Comparator<Phone>() {
@Override
public int compare(Phone ph1, Phone ph2) {
return ph1.getPrice().compareTo(ph2.getPrice());
}
};
After Java 8
Comparator<Phone> phoneComparator = (Phone p1, Phone p2) -> p1.getPrice().compareTo(p2.getPrice());
Components of Lambda
Lambda has three components
- List of parameters
- The Arrow: Arrow separates the parameter from the body.
- Body of the lambda
Examples
(String s) -> s.length()
- Take one parameter string and return (implicit) an int value.
(Phone p) -> p.getPrice() > 100000
- Take one parameter phone and return true if the price of the phone is greater than 1L
(int arg1, int arg2) -> { System.out.println("I am printing arg1 : " + arg1);
}
- Take two parameters and return nothing.
Style of the body of Lambda
A lambda body can have two different styles
EXPRESSION STYLE
(parameters) -> expression
BLOCK STYLE
(parameters) -> {statements;}
Where and How to use Lambda
Lambda expression should be used in the context of the functional interfaces.
Functional Interface
The interface defines precisely one abstract method.
Example is PhonePredicate
public interface PhonePredicate {
boolean test(Phone phone);
}
How does lambda expression utilize functional interfaces?
Lambda expression provides you provide an inline implementation of the functional interface.
Eg.
Runnable instance without lambda
Runnable r = new Runnable() {
public void run() {
System.out.println("Hello World Runnable");
}
};
Runnable instance with lambda
Runnable r = () -> System.out.println("Hello World Runnable");
Functional Descriptor
The signature of the lambda expression is determined by the functional interface abstract method. Thus the abstract method is a functional descriptor.
New Functional interfaces in Java 8
Java 8 introduced several new functional interfaces in the package java.util.function
- Predicate: Transform an object in a boolean value, especially used for conditions
- Consumer: Consume an object and returns nothing.
- Function: Transform one object to another.