Lambda expressions were introduced in Java 8. They provide a much cleaner syntax than previous Java versions for the solution to several common programming tasks in Java. Here are some examples
- writing a custom sort for an
ArrayListof objects (or anyCollectionof objects) - writing event handlers for Swing GUIs
- writing event handlers for web applications
References:
Example of Lambda Expressions
One of the most common examples of lambdas expressions is to specify an instance of a class that implements the Comparator
Suppose you have a Dog object with getters for name and weight:
public class Dog {
private String name;
private double weight;
public String getName() { return name; }
public double getWeight() { return weight; }
public Dog(String name, double weight) {
this.name = name;
this.weight = weight;
}
public String toString () {
return "[" + name + "," + weight + "]";
}
}
A Comparator<Dog> would look like this:
public class DogWeightComparator implements java.util.Comparator<Dog> {
@Override
public int compare(Dog o1, Dog o2) {
return Double.compare(o1.getWeight(),o2.getWeight());
}
}
But if this class is only going to ever be instantiated once, e.g. in a sort like this one:
import java.util.ArrayList;
public class SortDogs2 {
public static void main(String [] args) {
ArrayList<Dog> kennel = new ArrayList<Dog>();
kennel.add(new Dog("Fido",15));
kennel.add(new Dog("Spot",20));
kennel.add(new Dog("Puddles",8));
kennel.add(new Dog("Doge",45));
kennel.add(new Dog("Catepillar",90));
System.out.println("Not sorted: " + kennel);
java.util.Collections.sort(kennel,new DogWeightComparator());
System.out.println("Sorted by weight " + kennel);
}
}
Then it is much easier to specify the comparator as a lambda function like this:
Comparator<Dog> sortByWeight = (dog1, dog2) -> Double.compare(dog1.getWeight(),dog2.getWeight());
The lambda expression:
(dog1, dog2) -> Double.compare(dog1.getWeight(),dog2.getWeight())
Can be interpreted this way:
-
Recall that the
comparemethod ofComparator<T>has this signature:int compare (T o1, T o2)and is expected to return a
intvalue that is:- less than zero if
o1 < o2, that iso1should appear beforeo2when sortig in ascending order. - equal to zero if
o1.equals(o2)(that is,o1ando2can appear in either order when sorting) - greater than zero if
o1 > o2, that iso1should appear aftero2when sortig in ascending order.
- less than zero if
Because the lambda expression must have the type Comparator<Dog>, we immediately know that this is an implementation of the compare method of the interface Comparator<Dog>.
- It has to be:
Comparator<T>is marked with the annotation@FunctionalInterface, which means it is an interface with *exactly one abstract method *(no more than one, no fewer than one). - Therefore, we can infer that
(dog1, dog2)is the parameter list for thecomparemethod. - We don’t have to specify
(Dog dog1, Dog dog2); that would be redundant, since we can infer the types ofdog1anddog2 - Similarly, with a lambda, the value on the right hand side of the arrow (
->) is the return value. - For lambdas that are single line implementations, i.e.
return expression;, we can omit the braces{}and thereturnstatement, and just put theexpressionon the right hand side of the arrow (->).
Variations on Lambdas:
It all comes down to the method that you are implementing.
Arguments:
- If there are no parameters to the method, you write
()->expression. The empty parameter list()shows that there are no arguments. - There can be any number of arguments, e.g.
(x)->expression,(x,y)->expression,(x,y,z)->expression, etc.
Return value:
- If the implementation is just
return expression, you can leave out the braces and the keywordreturn. - But optionally, you can put a set of braces, and as many statements as you want. For example, these are both valid:
First version:
Comparator<Dog> sortByWeight = (dog1, dog2) -> Double.compare(dog1.getWeight(),dog2.getWeight());
Second version:
Comparator<Dog> sortByWeight = (dog1, dog2) -> {
System.out.println("I'm inside the sortByWeight comparator. Hi there!");
double dogWeight1 = dog1.getWeight();
double dogWeight2 = dog2.getWeight();
return Double.compare(dogWeight1, dogWeight2);
}