Java Notes
Learn Comparable and Comparator in Java — how to sort custom objects, implement compareTo(), write multiple Comparators, and use lambda expressions for concise sorting.
When you call Collections.sort() on a list of integers, Java knows how to sort them — numbers have a natural order. But what about a list of Student objects? Java does not know whether to sort by name, marks, or roll number. You have to tell it.
Two interfaces handle this: Comparable (built into the class) and Comparator (external sorting logic).
Comparable — Natural Order Built Into the Class
Implement Comparable<T> in the class itself to define its natural order. You write one compareTo() method.
Try it in WoHoCode
Edit the program, then run it here.
Run this example to see its output.
Line by line:
implements Comparable<Student>— this class can be naturally sorted.compareTo(Student other)— return negative ifthisshould come beforeother, zero if equal, positive ifothercomes first.this.marks - other.marks— ascending order. For descending, flip toother.marks - this.marks.Collections.sort(students)— works becauseStudentimplementsComparable.
Comparator — External Sorting Logic
Comparator is a separate object that defines a sort order. Use it when:
- You need multiple different sort orders
- You cannot modify the class (third-party library)
- You want to keep sorting logic separate
Try it in WoHoCode
Edit the program, then run it here.
Run this example to see its output.
Line by line:
Comparator.comparingInt(s -> s.marks)— creates a Comparator that extractsmarksfor comparison..reversed()— flips the order..thenComparing(s -> s.name)— secondary sort when marks are equal.students.sort(comparator)— sorts using the given Comparator, notcompareTo.
Comparable vs Comparator — Summary
| Comparable | Comparator | |
|---|---|---|
| Where defined | Inside the class | Separate class / lambda |
| Method | compareTo(T other) | compare(T o1, T o2) |
| Sort orders | One (natural) | Many (one per Comparator) |
| Used by | Collections.sort(list) | Collections.sort(list, comp) |
| Modify class needed? | Yes | No |
| Use when | One obvious natural order | Multiple orderings needed |
compareTo Return Value Rule
This applies to both compareTo and compare:
// return NEGATIVE — first argument (this / o1) should come BEFORE second
// return ZERO — equal, order doesn't matter
// return POSITIVE — second argument should come BEFORE first
// Ascending numbers: a - b
// Descending numbers: b - a
// Ascending strings: a.compareTo(b)
// Descending strings: b.compareTo(a)Common Mistake 1: Integer Overflow in compareTo
// WRONG — can overflow for large negative numbers
public int compareTo(Item other) {
return this.value - other.value; // if values are very large/small → overflow
}
// CORRECT — use Integer.compare
public int compareTo(Item other) {
return Integer.compare(this.value, other.value);
}Common Mistake 2: Breaking the Contract
compareTo must be consistent: if a.compareTo(b) < 0 then b.compareTo(a) must be > 0. Violating this breaks sorting and TreeSet/TreeMap.
Practice Task
Task: Create a class Product with fields name (String), price (double), and rating (double). Implement Comparable<Product> to sort by price ascending. Create three separate Comparators:
- By rating descending
- By name alphabetically
- By price descending, then rating descending
Create a list of 4 products and test all three Comparators.
Solution:
Try it in WoHoCode
Edit the program, then run it here.
Run this example to see its output.
What to observe: products.sort(null) uses the class's own compareTo (natural order by price). Each Comparator is independent — you can switch sorting strategy on the fly. Try adding thenComparing(p -> p.name) to break ties alphabetically.
Continue the lesson path