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
ArrayList
of objects (or anyCollection
of 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
compare
method ofComparator<T>
has this signature:int compare (T o1, T o2)
and is expected to return a
int
value that is:- less than zero if
o1 < o2
, that iso1
should appear beforeo2
when sortig in ascending order. - equal to zero if
o1.equals(o2)
(that is,o1
ando2
can appear in either order when sorting) - greater than zero if
o1 > o2
, that iso1
should appear aftero2
when 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 thecompare
method. - We don’t have to specify
(Dog dog1, Dog dog2)
; that would be redundant, since we can infer the types ofdog1
anddog2
- 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 thereturn
statement, and just put theexpression
on 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);
}