Java Comparator Interface
The Comparator interface in Java is used to define custom ordering logic for objects.
It allows you to sort objects externally, without modifying the class whose objects are being compared.
Introduced in java.util, Comparator is a cornerstone of sorting, ordering, and stream-based operations.
Why Comparator Exists
Java provides two ways to define sorting:
- Comparable → Natural ordering (inside the class)
- Comparator → Custom ordering (outside the class)
Comparator is used when:
- You cannot modify the class
- You want multiple sorting strategies
- Sorting logic should be decoupled from the model
Comparator vs Comparable
| Feature | Comparable | Comparator |
|---|---|---|
| Package | java.lang | java.util |
| Method | compareTo() | compare() |
| Modifies class | Yes | No |
| Multiple orderings | No | Yes |
| Lambda-friendly | Limited | Yes |
Comparator Interface Definition
@FunctionalInterface
public interface Comparator<T> {
int compare(T o1, T o2);
}
Return values meaning
| Return | Meaning |
|---|---|
< 0 | o1 comes before o2 |
0 | o1 equals o2 |
> 0 | o1 comes after o2 |
Simple Example
Sorting integers in descending order
Comparator<Integer> desc = (a, b) -> b - a;
Collections.sort(list, desc);
Sorting Custom Objects
Example class
class Employee {
int id;
String name;
double salary;
}
Sort by salary (ascending)
Comparator<Employee> bySalary =
(e1, e2) -> Double.compare(e1.salary, e2.salary);
Collections.sort(employees, bySalary);
Sort by name (alphabetical)
Comparator<Employee> byName =
(e1, e2) -> e1.name.compareTo(e2.name);
Comparator with Lambda Expressions
Since Comparator is a functional interface, lambdas work naturally.
employees.sort((a, b) -> a.id - b.id);
Cleaner alternative:
employees.sort(Comparator.comparing(e -> e.id));
Comparator Utility Methods (Java 8+)
comparing()
Comparator<Employee> bySalary =
Comparator.comparing(Employee::getSalary);
reversed()
Comparator<Employee> bySalaryDesc =
Comparator.comparing(Employee::getSalary).reversed();
thenComparing() (Multiple conditions)
Comparator<Employee> byDeptThenSalary =
Comparator.comparing(Employee::getDepartment)
.thenComparing(Employee::getSalary);
Null Handling
nullsFirst()
Comparator<Employee> comp =
Comparator.nullsFirst(
Comparator.comparing(Employee::getName)
);
nullsLast()
Comparator<Employee> comp =
Comparator.nullsLast(
Comparator.comparing(Employee::getName)
);
Comparator with Streams
List<Employee> sorted =
employees.stream()
.sorted(Comparator.comparing(Employee::getSalary))
.toList();
Descending:
employees.stream()
.sorted(Comparator.comparing(Employee::getSalary).reversed())
.toList();
Sorting Maps Using Comparator
Sort Map by Key
Map<String, Integer> sorted =
new TreeMap<>(Comparator.reverseOrder());
Sort Map Entries by Value
map.entrySet()
.stream()
.sorted(Map.Entry.comparingByValue())
.forEach(System.out::println);
Comparator in TreeSet / TreeMap
Tree-based collections rely on Comparator for ordering.
Set<Employee> set =
new TreeSet<>(Comparator.comparing(Employee::getId));
⚠️ Comparator must ensure consistent ordering, or elements may be lost.
Common Pitfalls
❌ Subtraction for comparison
(a, b) -> a - b // may overflow
✅ Use:
Integer.compare(a, b);
❌ Inconsistent comparison
Returning random or inconsistent values breaks TreeSet / TreeMap.
❌ Forgetting equals contract
Comparator should be consistent with equals where possible.
Comparator vs equals()
equals()checks logical equalityComparatorchecks ordering- They serve different purposes
Real-World Use Cases
- Sorting search results
- Ordering leaderboard data
- Multi-level sorting (date → priority → name)
- Custom UI sorting
- Stream pipelines
Interview Tips 🎯
- Prefer
Comparator.comparing()over manual lambdas - Mention immutability and reusability
- Avoid subtraction comparisons
- Explain difference between Comparable and Comparator clearly
Summary
- Comparator defines external sorting logic
- Supports multiple sorting strategies
- Functional, composable, and stream-friendly
- Essential for clean, flexible ordering logic
One-line takeaway
Comparator lets you decide how objects should be ordered without touching the object itself.