How to compare objects by multiple fields

Yuval Adam picture Yuval Adam · Dec 15, 2008 · Viewed 416.3k times · Source

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?

Answer

Display Name picture Display Name · Aug 26, 2014

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);
}