What is Comparator vs Comparable?
In Java, both `Comparable` and `Comparator` interfaces are used to define the order of objects. While they both provide sorting capabilities, they differ in how they achieve this and when they should be used, primarily concerning natural ordering versus custom ordering.
Comparable Interface
The Comparable interface is used to define the natural ordering of objects. It has a single method, compareTo(Object obj), which dictates how instances of the class should be ordered relative to each other. When a class implements Comparable, its objects can be sorted intrinsically without requiring external logic.
- Defines natural or default ordering.
- Implemented by the class itself whose objects are to be sorted.
- Has a single method:
public int compareTo(T o). - Modifies the class whose objects are being sorted.
- Used for default sorting behavior (e.g.,
Integer,String,Date).
class Student implements Comparable<Student> {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public int compareTo(Student other) {
// Sort by age in ascending order
return Integer.compare(this.age, other.age);
}
@Override
public String toString() {
return "Student{name='" + name + "', age=" + age + "}";
}
}
Comparator Interface
The Comparator interface provides a way to define custom ordering for objects. It is typically implemented as a separate class or an anonymous inner class/lambda expression, allowing for multiple sorting strategies for the same object type. It has the compare(Object obj1, Object obj2) method.
- Defines custom or alternative ordering.
- Implemented by a separate class, anonymous class, or lambda expression.
- Has a single method:
public int compare(T o1, T o2). - Does not modify the class whose objects are being sorted.
- Used when natural ordering is not suitable or multiple sorting criteria are needed.
import java.util.Comparator;
class StudentNameComparator implements Comparator<Student> {
@Override
public int compare(Student s1, Student s2) {
// Sort by name in alphabetical order
return s1.getName().compareTo(s2.getName());
}
}
// Usage example (assuming Student class from above):
// List<Student> students = new ArrayList<>();
// students.add(new Student("Alice", 25));
// students.add(new Student("Bob", 22));
// Collections.sort(students, new StudentNameComparator());
Key Differences
| Feature | Comparable | Comparator |
|---|---|---|
| Purpose | Defines natural/default sorting order. | Defines custom/alternative sorting orders. |
| Implementation | Implemented by the class whose objects are being sorted. | Implemented by a separate class, anonymous class, or lambda expression. |
| Method | `int compareTo(T obj)` | `int compare(T obj1, T obj2)` |
| Modification | Modifies the class itself. | Does not modify the class. |
| Package | `java.lang` | `java.util` |
| Multiple Sorts | Only one natural sort order possible. | Multiple custom sort orders possible. |
When to Use Which?
- Use
Comparablewhen you want to define a single, default sorting order for the objects of a class. - Use
Comparablewhen you have control over the class's source code and can modify it to implement the interface.
- Use
Comparatorwhen you need multiple ways to sort a collection of objects. - Use
Comparatorwhen you don't have control over the class's source code (e.g., sorting objects from a third-party library). - Use
Comparatorwhen the class already implementsComparable, but you need a different sorting criterion.