What is the difference between Comparable and Comparator in Java?
Comparable is implemented by the class itself and defines its natural ordering — the single, built-in way its instances should be ordered. The class supplies a compareTo method, and that ordering is then used automatically by Collections.sort, by the sort method on lists, and by the sorted collections such as TreeSet and TreePriorityQueue.
Comparator is a separate object that defines an external ordering. You pass it to the sorting method, so the class does not have to know about it, and you can have several different comparators for the same class — by name, by age, by score.
The distinction matters when you choose between them. Implement Comparable when there is one obvious natural order for the type — a number by its value, a date by its instant. Use a Comparator when the ordering depends on the context, when the type comes from a library you cannot change, or when you need more than one ordering at the same time.
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<Emp> staff = new ArrayList<>(List.of(
new Emp("Ada", 36), new Emp("Alan", 41), new Emp("Grace", 36)));
// Natural order: Comparable.
Collections.sort(staff);
System.out.println("by age : " + staff);
// Explicit order: Comparator.
staff.sort((a, b) -> a.getName().compareTo(b.getName()));
System.out.println("by name : " + staff);
}
}
class Emp implements Comparable<Emp> {
private final String name;
private final int age;
Emp(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public int compareTo(Emp other) {
return Integer.compare(this.age, other.age);
}
String getName() {
return name;
}
int getAge() {
return age;
}
@Override
public String toString() {
return name + "(" + age + ")";
}
}The output shows the two mechanisms. The first sort used the class's own natural ordering, so the employees come out by age. The second sort passed an explicit comparator and reordered them by name.
Two rules to remember. The compare method must return a negative number, zero or a positive number — never the difference of two values, because that overflows for large numbers, so use Integer.compare or Long.compare. And a Comparator should be consistent with equals, otherwise sorted collections behave surprisingly: TreeSet will treat two elements that compare equal as the same element even when they are not equals-equal.