Reputation: 51473
I have a List<DefaultMutableTreeNode>
and want to sort the list by a property of the userObject
with a custom comparator.
In order to provide a simple example I will use the user object Person
public class Person {
private String firstname;
private String lastname;
public Person(String firstname, String lastname) {
this.firstname = firstname;
this.lastname = lastname;
}
public String getFirstname() {
return firstname;
}
public String getLastname() {
return lastname;
}
}
and a custom comparator
public class PersonComparator implements Comparator<Person> {
@Override
public int compare(Person o1, Person o2) {
// to keep the example simple I just compare the firstnames here
return o1.getFirstname().compareTo(o2.getFirstname());
}
}
My first thought was to use Comparator.comparing
with a method reference as key extractor and a key comparator.
public static void main(String[] args) {
List<DefaultMutableTreeNode> nodes = new ArrayList<DefaultMutableTreeNode>();
nodes.add(new DefaultMutableTreeNode(new Person("James", "Smith")));
nodes.add(new DefaultMutableTreeNode(new Person("Paul", "Clark")));
nodes.add(new DefaultMutableTreeNode(new Person("Anthony", "Brown")));
Comparator<Person> myComparator = new PersonComparator();
nodes.sort(Comparator.comparing(DefaultMutableTreeNode::getUserObject, myComparator));
}
But this gives me (of course) a compiler error since the DefaultMutableTreeNode.getUserObject()
returns an Object
and not a Person
.
How can I cast the retrun type of the lambda method reference DefaultMutableTreeNode::getUserObject
?
Or do you have any other options?
EDIT:
I can do it this way, but is there an easier way? (in one line)
Function<DefaultMutableTreeNode, Object> userObject = DefaultMutableTreeNode::getUserObject;
nodes.sort(Comparator.comparing(userObject.andThen(Person.class::cast), myComparator));
Upvotes: 1
Views: 1630
Reputation: 137289
Your question talks about "lambda method reference" but this doesn't exist: there are lambda expressions, and there are method-references. A method-reference is a special feature where, instead of writing a lambda expression that would simply invoke another existing method, you use the ::
operator to refer to that method directly by name.
But in this case, since getUserObject
returns an Object
and not a Person
, you won't be able to directly use a method-reference here: you need to have more code than simply refering to getUserObject
: a cast is needed.
As such, use a lambda expression:
nodes.sort(Comparator.comparing(t -> (Person) t.getUserObject(), myComparator));
Another way would be to create a method that returns a Person
instead of an Object
, and refer to that method:
private static Person getPerson(DefaultMutableTreeNode node) {
return (Person) node.getUserObject();
}
// assuming "getPerson" in a class called MyClass
nodes.sort(Comparator.comparing(MyClass::getPerson, myComparator));
Note that the PersonComparator
can be written more simply with
Comparator<Person> myComparator = Comparator.comparing(Person::getFirstname);
Upvotes: 4