Comparable — natural ordering defined inside the class itself. Comparator — custom external ordering defined outside the class.
Think of it like a library: Comparable is like the library's own alphabetical sorting system built into the catalog. Comparator is like a librarian who can sort books by any criteria you choose — color, size, publication date, or popularity.
Comparable (java.lang.Comparable):
Comparable<T>.compareTo(T o) method — returns negative, zero, or positive.1public class Person implements Comparable<Person> {2 private String name;3 private int age;45 public Person(String name, int age) {6 this.name = name;7 this.age = age;8 }910 @Override11 public int compareTo(Person other) {12 // Natural order: by name alphabetically13 int nameComparison = this.name.compareTo(other.name);14 if (nameComparison != 0) {15 return nameComparison;16 }17 // Tie-breaker: by age ascending18 return Integer.compare(this.age, other.age);19 }2021 @Override22 public String toString() {23 return name + " (age " + age + ")";24 }25}2627// Usage:28List<Person> people = new ArrayList<>();29people.add(new Person("Charlie", 30));30people.add(new Person("Alice", 25));31people.add(new Person("Bob", 35));32Collections.sort(people); // Uses compareTo33// Output: Alice (25), Bob (35), Charlie (30)
Comparator (java.util.Comparator):
compare(T o1, T o2) method.1public class Person {2 private String name;3 private int age;45 public Person(String name, int age) {6 this.name = name;7 this.age = age;8 }910 // Getters11 public String getName() { return name; }12 public int getAge() { return age; }13}1415// Comparator by age16Comparator<Person> byAge = (p1, p2) -> Integer.compare(p1.getAge(), p2.getAge());1718// Comparator by name length19Comparator<Person> byNameLength =20 (p1, p2) -> Integer.compare(p1.getName().length(), p2.getName().length());2122// Using them:23people.sort(byAge); // Sort by age24people.sort(byNameLength); // Sort by name length25people.sort(byAge.reversed()); // Reverse age order2627// Chaining with Comparator.comparing:28people.sort(29 Comparator.comparing(Person::getAge)30 .thenComparing(Person::getName)31);
Key differences:
compareTo() on this vs other.compare() takes two separate parameters.Collections.sort(list) with one arg.Collections.sort(list, comparator) with two args.When to use which:
Common mistake:
compareTo must be consistent with equals. If compareTo returns 0 but equals returns false, collections like TreeSet will behave incorrectly — they might not detect duplicates properly.Java 8+ Tip: The Comparator interface now has default methods like thenComparing(), reversed(), nullsFirst(), and nullsLast() that make chaining comparators extremely clean.