Reputation: 1759
I'm learning about lambda expressions. I don't understand how a comparator is returned from method reference.
I want to sort a list of persons by age.
To do that, I have a method to find the age difference:
public int ageDifference(final Person other) {
return age - other.age;
}
The sorted
method needs as parameter a Comparator
Stream<T> sorted(Comparator<? super T> comparator);
My lambda expression is:
people.stream()
.sorted(Person::ageDifference)
.collect(toList());
How Person::ageDifference
is trasformed in a Comparator<Person>
?
My complete example:
public class Person {
private final String name;
private final int age;
public Person(final String theName, final int theAge) {
name = theName;
age = theAge;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public int ageDifference(final Person other) {
return age - other.age;
}
public String toString() {
return String.format("%s - %d", name, age);
}
public static void main (String args[] ){
final List<Person> people = Arrays.asList(
new Person("John", 10),
new Person("Greg", 30),
new Person("Sara", 20),
new Person("Jane", 15));
List<Person> ascendingAge =
people.stream()
.sorted(Person::ageDifference)
.collect(toList());
System.out.println(ascendingAge);
}
}
Output: [John - 10, Jane - 15, Sara - 20, Greg - 30]
Upvotes: 0
Views: 280
Reputation: 272905
I guess your main confusion is this:
Comparator<T>
represents a method that takes two parameters of typeT
and returns aint
. MyageDifference
method accepts only onePerson
parameter. How can that become aComparator<Person>
?
Note that ageDifference
is an instance method. To call it, not only do you need the parameters, you also need an instance of Person
. In this case, you need 2 Person
s to call the method - one on which you call ageDifference
, and the other one you pass as a parameter:
me.ageDifference(someoneElse)
^ ^
| |
Two people!
Isn't this just like a static
method that accepts two parameters?
Therefore, Java is smart enough to know that you need two people to call Person::ageDifference
, so the method reference is treated as having two parameters.
In general, an instance method of a class T
accepting parameters P1
, P2
... Pn
and returning type R
can be treated as a static method accepting parameters T
, P1
, P2
... Pn
and returning R
.
Upvotes: 5