How a Comparator is created from method reference?
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]
java lambda
add a comment |
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]
java lambda
4
stackoverflow.com/questions/17913409/what-is-a-sam-type-in-java
– leonardkraemer
Nov 20 '18 at 18:26
1
Right,Comparatoris a SAM type. A Single Abstract Method. So the compiler "just knows" to substitute theComparatortype and have it call the method you supply,Person::ageDifference. The link Leonard Kraemer supplied explains in more detail.
– markspace
Nov 20 '18 at 18:34
1
As a lambda it'd look like:(p1, p2) -> p1.ageDifference(p2)
– Slaw
Nov 20 '18 at 18:43
add a comment |
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]
java lambda
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]
java lambda
java lambda
edited Nov 20 '18 at 19:00
Jesus Zavarce
asked Nov 20 '18 at 18:23
Jesus ZavarceJesus Zavarce
1,064819
1,064819
4
stackoverflow.com/questions/17913409/what-is-a-sam-type-in-java
– leonardkraemer
Nov 20 '18 at 18:26
1
Right,Comparatoris a SAM type. A Single Abstract Method. So the compiler "just knows" to substitute theComparatortype and have it call the method you supply,Person::ageDifference. The link Leonard Kraemer supplied explains in more detail.
– markspace
Nov 20 '18 at 18:34
1
As a lambda it'd look like:(p1, p2) -> p1.ageDifference(p2)
– Slaw
Nov 20 '18 at 18:43
add a comment |
4
stackoverflow.com/questions/17913409/what-is-a-sam-type-in-java
– leonardkraemer
Nov 20 '18 at 18:26
1
Right,Comparatoris a SAM type. A Single Abstract Method. So the compiler "just knows" to substitute theComparatortype and have it call the method you supply,Person::ageDifference. The link Leonard Kraemer supplied explains in more detail.
– markspace
Nov 20 '18 at 18:34
1
As a lambda it'd look like:(p1, p2) -> p1.ageDifference(p2)
– Slaw
Nov 20 '18 at 18:43
4
4
stackoverflow.com/questions/17913409/what-is-a-sam-type-in-java
– leonardkraemer
Nov 20 '18 at 18:26
stackoverflow.com/questions/17913409/what-is-a-sam-type-in-java
– leonardkraemer
Nov 20 '18 at 18:26
1
1
Right,
Comparator is a SAM type. A Single Abstract Method. So the compiler "just knows" to substitute the Comparator type and have it call the method you supply, Person::ageDifference. The link Leonard Kraemer supplied explains in more detail.– markspace
Nov 20 '18 at 18:34
Right,
Comparator is a SAM type. A Single Abstract Method. So the compiler "just knows" to substitute the Comparator type and have it call the method you supply, Person::ageDifference. The link Leonard Kraemer supplied explains in more detail.– markspace
Nov 20 '18 at 18:34
1
1
As a lambda it'd look like:
(p1, p2) -> p1.ageDifference(p2)– Slaw
Nov 20 '18 at 18:43
As a lambda it'd look like:
(p1, p2) -> p1.ageDifference(p2)– Slaw
Nov 20 '18 at 18:43
add a comment |
1 Answer
1
active
oldest
votes
I guess your main confusion is this:
Comparator<T>represents a method that takes two parameters of typeTand returns aint. MyageDifferencemethod accepts only onePersonparameter. 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 Persons 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.
to complete your good answer, the reason why the code above compiles is in the way of how the new lambda functionality works in Java 8. It relies on a concept which is informally known as "single abstract method (SAM)" interfaces. The basic idea is that any interface with one abstract method can be automatically implemented by any lambda or method reference, if the lambda or method reference matches the SAM in the interface.
– Jesus Zavarce
Dec 13 '18 at 8:08
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53399226%2fhow-a-comparator-is-created-from-method-reference%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
I guess your main confusion is this:
Comparator<T>represents a method that takes two parameters of typeTand returns aint. MyageDifferencemethod accepts only onePersonparameter. 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 Persons 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.
to complete your good answer, the reason why the code above compiles is in the way of how the new lambda functionality works in Java 8. It relies on a concept which is informally known as "single abstract method (SAM)" interfaces. The basic idea is that any interface with one abstract method can be automatically implemented by any lambda or method reference, if the lambda or method reference matches the SAM in the interface.
– Jesus Zavarce
Dec 13 '18 at 8:08
add a comment |
I guess your main confusion is this:
Comparator<T>represents a method that takes two parameters of typeTand returns aint. MyageDifferencemethod accepts only onePersonparameter. 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 Persons 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.
to complete your good answer, the reason why the code above compiles is in the way of how the new lambda functionality works in Java 8. It relies on a concept which is informally known as "single abstract method (SAM)" interfaces. The basic idea is that any interface with one abstract method can be automatically implemented by any lambda or method reference, if the lambda or method reference matches the SAM in the interface.
– Jesus Zavarce
Dec 13 '18 at 8:08
add a comment |
I guess your main confusion is this:
Comparator<T>represents a method that takes two parameters of typeTand returns aint. MyageDifferencemethod accepts only onePersonparameter. 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 Persons 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.
I guess your main confusion is this:
Comparator<T>represents a method that takes two parameters of typeTand returns aint. MyageDifferencemethod accepts only onePersonparameter. 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 Persons 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.
answered Nov 20 '18 at 18:40
SweeperSweeper
68.7k1073140
68.7k1073140
to complete your good answer, the reason why the code above compiles is in the way of how the new lambda functionality works in Java 8. It relies on a concept which is informally known as "single abstract method (SAM)" interfaces. The basic idea is that any interface with one abstract method can be automatically implemented by any lambda or method reference, if the lambda or method reference matches the SAM in the interface.
– Jesus Zavarce
Dec 13 '18 at 8:08
add a comment |
to complete your good answer, the reason why the code above compiles is in the way of how the new lambda functionality works in Java 8. It relies on a concept which is informally known as "single abstract method (SAM)" interfaces. The basic idea is that any interface with one abstract method can be automatically implemented by any lambda or method reference, if the lambda or method reference matches the SAM in the interface.
– Jesus Zavarce
Dec 13 '18 at 8:08
to complete your good answer, the reason why the code above compiles is in the way of how the new lambda functionality works in Java 8. It relies on a concept which is informally known as "single abstract method (SAM)" interfaces. The basic idea is that any interface with one abstract method can be automatically implemented by any lambda or method reference, if the lambda or method reference matches the SAM in the interface.
– Jesus Zavarce
Dec 13 '18 at 8:08
to complete your good answer, the reason why the code above compiles is in the way of how the new lambda functionality works in Java 8. It relies on a concept which is informally known as "single abstract method (SAM)" interfaces. The basic idea is that any interface with one abstract method can be automatically implemented by any lambda or method reference, if the lambda or method reference matches the SAM in the interface.
– Jesus Zavarce
Dec 13 '18 at 8:08
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53399226%2fhow-a-comparator-is-created-from-method-reference%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
4
stackoverflow.com/questions/17913409/what-is-a-sam-type-in-java
– leonardkraemer
Nov 20 '18 at 18:26
1
Right,
Comparatoris a SAM type. A Single Abstract Method. So the compiler "just knows" to substitute theComparatortype and have it call the method you supply,Person::ageDifference. The link Leonard Kraemer supplied explains in more detail.– markspace
Nov 20 '18 at 18:34
1
As a lambda it'd look like:
(p1, p2) -> p1.ageDifference(p2)– Slaw
Nov 20 '18 at 18:43