🔗 Comparator vs Comparable
Feature | Comparable | Comparator |
---|---|---|
Interface location | java.lang (core package) | java.util (utility package) |
Purpose | Defines natural ordering of a class | Defines custom ordering for a class (outside the class itself) |
Where to implement? | In the class itself (the class “knows” how to compare itself) | In a separate class (the comparison logic is external) |
Method to implement | int compareTo(T o) | int compare(T o1, T o2) |
Works with | Collections like TreeSet , TreeMap , Arrays.sort() (natural order) | Collections.sort() with custom logic |
Flexibility | Only one ordering (natural order) | Can define multiple orderings for the same class |
Example use case | Entities with a clear default order (like String , Integer ) | Sorting objects differently based on user needs (e.g., sort by name , or by age ) |
📜 Example — Using Comparable
Imagine a class Person
where natural order is based on age
:
class Person implements Comparable<Person> {
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public int compareTo(Person other) {
return Integer.compare(this.age, other.age); // Natural order = by age
}
@Override
public String toString() {
return name + " (" + age + ")";
}
}
Sorting (Natural Order – Age):
List<Person> people = List.of(new Person("Alice", 30), new Person("Bob", 25));
List<Person> sorted = new ArrayList<>(people);
Collections.sort(sorted); // Works because Person implements Comparable
System.out.println(sorted); // [Bob (25), Alice (30)]
📜 Example — Using Comparator
Now you want to sort by name sometimes, and by age other times. A Comparator
lets you do that:
class Person {
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return name + " (" + age + ")";
}
}
// Comparator to sort by name
Comparator<Person> byName = (p1, p2) -> p1.name.compareTo(p2.name);
// Comparator to sort by age (if not using Comparable)
Comparator<Person> byAge = Comparator.comparingInt(p -> p.age);
Usage:
List<Person> people = List.of(new Person("Alice", 30), new Person("Bob", 25));
List<Person> sortedByName = new ArrayList<>(people);
Collections.sort(sortedByName, byName); // Sort by name
System.out.println(sortedByName); // [Alice (30), Bob (25)]
List<Person> sortedByAge = new ArrayList<>(people);
Collections.sort(sortedByAge, byAge); // Sort by age
System.out.println(sortedByAge); // [Bob (25), Alice (30)]
🔥 Summary Table
Feature | Comparable | Comparator |
---|---|---|
Defines ordering | Inside the class itself | Outside the class (external) |
Flexibility | One order | Multiple orders (choose per sort) |
Typical usage | Natural sorting (like alphabetic or numeric order) | Custom sorting (like by date, length, or multiple fields) |
Sort method | Collections.sort(list) works directly | Collections.sort(list, comparator) needs comparator provided |
⚠️ When to Use What?
Case | Use |
---|---|
Class has a clear natural order (like numbers, dates) | Comparable |
You want to sort the same class in different ways (by name, age, etc.) | Comparator |
🎯 Quick Tip for Interviews
✅ Always mention Comparable
is in the class itself, and Comparator
is outside the class.
✅ Mention Comparable
is like “self-sorting,” while Comparator
allows “external sorting.”
✅ You can even combine both! A class can implement Comparable
for default order, but you can still create Comparator
s for other orderings.