How to compare objects by multiple fields
Assume you have some objects which have several fields they can be compared by:
public class Person {
private String firstName;
private String lastName;
private String age;
/* Constructors */
/* Methods */
}
So in this example, when you ask if:
a.compareTo(b) > 0
you might be asking if a's last name comes before b's, or if a is older than b, etc...
What is the cleanest way to enable multiple comparison between these kinds of objects without adding unnecessary clutter or overhead?
-
java.lang.Comparable
interface allows comparison by one field only - Adding numerous compare methods (i.e.
compareByFirstName()
,compareByAge()
, etc...) is cluttered in my opinion.
So what is the best way to go about this?
With Java 8:
Comparator.comparing((Person p)->p.firstName)
.thenComparing(p->p.lastName)
.thenComparingInt(p->p.age);
If you have accessor methods:
Comparator.comparing(Person::getFirstName)
.thenComparing(Person::getLastName)
.thenComparingInt(Person::getAge);
If a class implements Comparable then such comparator may be used in compareTo method:
@Override
public int compareTo(Person o){
return Comparator.comparing(Person::getFirstName)
.thenComparing(Person::getLastName)
.thenComparingInt(Person::getAge)
.compare(this, o);
}
You should implement Comparable <Person>
. Assuming all fields will not be null (for simplicity sake), that age is an int, and compare ranking is first, last, age, the compareTo
method is quite simple:
public int compareTo(Person other) {
int i = firstName.compareTo(other.firstName);
if (i != 0) return i;
i = lastName.compareTo(other.lastName);
if (i != 0) return i;
return Integer.compare(age, other.age);
}