Comparable vs Comparator
Both define how to order objects. The difference is where the ordering lives and how many you can have:
- Comparable: the class orders itself by implementing
Comparable<T>and itscompareTo(T other)method. That's the object's natural order, and there's only one.Collections.sort(list),TreeSetandTreeMapuse it by default.String,IntegerandLocalDateare Comparable. - Comparator: a separate object with a
compare(a, b)method. You can have as many as you like, and you can sort classes you can't modify. Since Java 8 you rarely write one by hand:Comparator.comparing,thenComparing,reversed,nullsFirstandcomparingIntbuild them for you.
Rule of thumb: give a class a Comparable natural order only if there's one obvious way to order it (by id, by date). Use Comparators for everything else, such as the different sort options on a web page.
Side by side
| Comparable | Comparator | |
|---|---|---|
| Package | java.lang | java.util |
| Method | compareTo(T other) | compare(T a, T b) |
| Defined | Inside the class being sorted | Outside, as a separate object or lambda |
| How many orders | One (the natural order) | As many as you need |
| Need to change the class? | Yes | No: works for any class |
| Java 8 helpers | None | comparing, thenComparing, reversed, nullsFirst |
| Used by | Collections.sort(list), TreeSet, TreeMap by default | list.sort(cmp), new TreeSet<>(cmp), stream.sorted(cmp) |
Example
record Employee(int id, String name, double salary) implements Comparable<Employee> {
@Override public int compareTo(Employee other) {
return Integer.compare(id, other.id); // natural order: by id
}
}
List<Employee> staff = new ArrayList<>(List.of(
new Employee(3, "Ravi", 90_000), new Employee(1, "Asha", 120_000), new Employee(2, "Meera", 90_000)));
Collections.sort(staff); // by id (Comparable)
staff.sort(Comparator.comparingDouble(Employee::salary).reversed()
.thenComparing(Employee::name)); // salary high to low, then name (Comparator)Common mistake
Implementing compareTo with subtraction. It works in tests with small numbers and fails in production with large ones.
Under the hood
Never compare with subtraction (return a.age - b.age): it overflows for large values and gives wrong orders. Use Integer.compare or Comparator.comparingInt. Keep natural orders consistent with equals() (compareTo returns 0 exactly when equals is true), or sorted sets and maps will treat unequal objects as duplicates. The lesson "Sorting objects" covers more comparator techniques.
Check yourself
Which interface would you use to sort a class from a library you can't change?
How this connects
Know these first
Where this leads
You've reached the end of this thread. Try a learning path for what's next.
Part of Java 8 and collections, practically.
Was this lesson helpful?
Finished reading? Mark it complete to track your progress.