Stage 3: Core APIs, lesson 4 of 12

Sorting objects: Comparable and Comparator

Intermediate3 min read@since 16Code runs on your Java 25
Explain it forThe essentials plus production detail and pitfalls.

To sort your own objects, Java needs to know how two of them compare.

Comparable gives a class its natural order by implementing compareTo: return a negative number if this comes first, zero if equal, positive if after. String, Integer and LocalDate already implement it.

Comparator defines an order from outside the class, so you can have many. Java 8's factory methods keep them readable:

  • Comparator.comparing(Student::name)
  • .thenComparing(…) for tie-breakers
  • .reversed() and Comparator.comparingInt(…) (no boxing)
  • Comparator.nullsLast(…) when values can be null

Sort with list.sort(comparator) or stream.sorted(comparator). Sorting is stable: equal elements keep their relative order.

Example

Java
record Student(String name, int marks, LocalDate joined) implements Comparable<Student> {
    @Override
    public int compareTo(Student other) {             // natural order: by name
        return name.compareTo(other.name);
    }
}

List<Student> list = new ArrayList<>(List.of(
    new Student("Ravi", 81, LocalDate.of(2025, 6, 1)),
    new Student("Asha", 92, LocalDate.of(2025, 1, 15)),
    new Student("Kabir", 81, LocalDate.of(2024, 11, 3))));

Collections.sort(list);                               // Asha, Kabir, Ravi

list.sort(Comparator.comparingInt(Student::marks).reversed()
                    .thenComparing(Student::joined));
// Asha (92), then Kabir (81, joined earlier), then Ravi (81)

Student top = Collections.max(list, Comparator.comparingInt(Student::marks));

Common mistake

Writing compare as return a.marks() - b.marks(). It can overflow and give wrong results; use Integer.compare or Comparator.comparingInt.

Under the hood

Keep compareTo consistent with equals: if compareTo returns 0 for objects that aren't equal, TreeSet and TreeMap treat them as duplicates and keep only one. Never compare with subtraction (a - b), which overflows for large or negative values; use Integer.compare(a, b). List.sort uses TimSort, which is stable and fast on partly sorted data.

Check yourself

What should compareTo return when this should come before other?

How this connects

Where this leads

You've reached the end of this thread. Try a learning path for what's next.

Part of Crack the Java interview.

Was this lesson helpful?

Finished reading? Mark it complete to track your progress.