Comparable vs Comparator in Java
Understanding Sorting Mechanisms with Real Examples
Introduction
Sorting is one of the most common operations when working with collections in Java.
Java provides two interfaces for custom sorting:
- Comparable — for natural ordering of objects.
- Comparator — for custom or multiple orderings.
Understanding these interfaces is essential for working with sorted collections, priority queues, and other data structures.
This blog will cover:
- What Comparable and Comparator are.
- Key differences.
- How to implement each.
- Practical examples with custom classes.
- Advantages and limitations of each approach.
1. Comparable Interface
Definition
The Comparable interface is part of the java.lang package.
It is used to define natural ordering for objects of a class.
Signature:
public interface Comparable {
int compareTo(T o);
}
Rules for compareTo:
- Return a negative integer if this object is less than the other.
- Return zero if equal.
- Return a positive integer if greater.
Example: Comparable Implementation
Let’s create a Student class sorted by marks.
class Student implements Comparable {
String name;
int marks;
public Student(String name, int marks) {
this.name = name;
this.marks = marks;
}
@Override
public int compareTo(Student other) {
return this.marks - other.marks; // ascending order by marks
}
@Override
public String toString() {
return name + " → " + marks;
}
}
Testing Comparable
import java.util.*;
public class ComparableTest {
public static void main(String[] args) {
List students = new ArrayList<>();
students.add(new Student("Alice", 85));
students.add(new Student("Bob", 75));
students.add(new Student("Charlie", 90));
Collections.sort(students);
for (Student s : students) {
System.out.println(s);
}
}
}
Output:
Bob → 75
Alice → 85
Charlie → 90
Explanation:
- The compareTo method defined natural ordering for Student.
2. Comparator Interface
Definition
The Comparator interface is part of the java.util package.
It is used for custom ordering, especially when:
- Multiple sort criteria are needed.
- We don’t want to modify the class itself.
- Sorting external or library classes.
Signature:
public interface Comparator {
int compare(T o1, T o2);
}
Example: Comparator Implementation
Sorting students by name instead of marks.
class NameComparator implements Comparator {
@Override
public int compare(Student s1, Student s2) {
return s1.name.compareTo(s2.name);
}
}
Testing Comparator
import java.util.*;
public class ComparatorTest {
public static void main(String[] args) {
List students = new ArrayList<>();
students.add(new Student("Alice", 85));
students.add(new Student("Bob", 75));
students.add(new Student("Charlie", 90));
Collections.sort(students, new NameComparator());
for (Student s : students) {
System.out.println(s);
}
}
}
Output:
Alice → 85
Bob → 75
Charlie → 90
Explanation:
- Comparator allows external control of sorting order.
3. Differences Between Comparable and Comparator
Feature | Comparable | Comparator |
---|---|---|
Package | java.lang | java.util |
Method | compareTo(T o) | compare(T o1, T o2) |
Sorting Type | Natural ordering | Custom ordering |
Modification of Class | Required | Not required |
Multiple Sorting | Not possible directly | Possible |
Example Usage | Collections.sort(list) | Collections.sort(list, comparator) |
4. Practical Example with Multiple Comparators
Let’s sort students by marks descending and then by name ascending.
class MarksComparator implements Comparator {
@Override
public int compare(Student s1, Student s2) {
return s2.marks - s1.marks; // descending marks
}
}
class NameComparatorAsc implements Comparator {
@Override
public int compare(Student s1, Student s2) {
return s1.name.compareTo(s2.name); // ascending name
}
}
Testing:
students.sort(new MarksComparator().thenComparing(new NameComparatorAsc()));
5. Comparable vs Comparator in Java 8+ with Lambdas
Java 8 introduced lambdas, making comparators concise.
Example:
students.sort((s1, s2) -> s1.name.compareTo(s2.name));
students.sort(Comparator.comparing(Student::getMarks).reversed());
6. Advantages of Comparable
- Simple to use.
- Natural ordering is built into the class.
- Works directly with Collections.sort().
Limitations:
- Only one sorting criterion allowed.
- Requires modifying the class.
7. Advantages of Comparator
- Supports multiple sorting criteria.
- Does not require modifying the class.
- Works with any class, even library classes.
Limitations:
- More verbose without lambdas.
- Slightly more overhead compared to Comparable.
8. Real-World Use Cases
- Sorting custom objects in different orders.
- External sorting rules for library classes.
- Multi-field sorting in business applications (e.g., sorting employees by department, then salary).
- Dynamic sorting in APIs.
9. Summary Table
Aspect | Comparable | Comparator |
---|---|---|
Single sort | Yes | No |
Modify class | Yes | No |
Multiple sorts | No | Yes |
External sorting | No | Yes |
Java 8 Lambda | Limited | Powerful |
Conclusion
Comparable and Comparator in Java provide flexible sorting capabilities:
- Comparable → class-level natural ordering.
- Comparator → external, flexible ordering.
Choosing between them depends on the context:
- If there’s a single natural ordering → use Comparable.
- If multiple/custom orderings are required → use Comparator.
Understanding both deeply is crucial for writing clean and maintainable Java code that works with sorted collections effectively.
Next Blog- Custom Implementation of CyclicBarrier in Java