External Ordering with Comparator

Student implements Comparable<Student>, ordering by id. It also has a getGpa() method that returns a double. The registrar now wants the roster ranked by GPA, highest first, without changing Student.

Solution
public class GpaComparator implements Comparator<Student> {
  @Override
  public int compare(Student a, Student b) {
    return Double.compare(b.getGpa(), a.getGpa());
  }
}

Reversing the arguments to Double.compare (b before a) gives highest-to-lowest instead of lowest-to-highest.

Solution

A type has exactly one compareTo, so it gets exactly one natural order, and Student’s is already used for id. Changing it to GPA would lose the id order and would not give us a second order alongside it. Comparator is a separate object, so nothing stops us from writing one comparator per ordering we need, and none of them touches Student.

Use Comparable for a type’s single, obvious natural order. Use Comparator for an alternative order, for several different orders, or for a type you cannot or do not want to modify to add Comparable.