Comparable is the object’s built-in default sort, while Comparator is the outside rule you can swap in. Interviewers love this question because it checks whether you understand both sorting and how TreeSet/TreeMap decide uniqueness.
Question: Comparable vs Comparator.
Answer: Comparable is implemented by the class itself through compareTo() and gives that type one natural order. Comparator is a separate object with compare() that lets you define many different orderings for the same class. Use Comparable when there is one obvious default order; use Comparator when you need flexible, reusable, or temporary sorting rules.
Interview-Ready Answer: I’d say Comparable defines the natural order inside the class itself using compareTo(), so a type has one default way to be sorted. Comparator is external and defines custom ordering with compare(), so I can sort the same objects by age, salary, name, or anything else without changing the class. A useful detail is that sorted collections like TreeSet and TreeMap also use that ordering to decide when two objects count as the same key.
Comparable is for a class that knows how it should be ordered by default. The method is compareTo മറ്റെരേഖ? No need
Comparator is an external comparison rule. It is a functional interface, meaning it has one abstract method, so you can use a lambda in Java 8+.
Comparable, Java calls compareTo() on the objects themselves.Comparator, Java calls compare() on that comparator instead.TreeSet and TreeMap, every insert, lookup, and removal walks a tree and compares nodes on the way down.0, the structure treats the two values as equal for ordering purposes.| Aspect | Comparable | Comparator |
|---|---|---|
| Where defined | Inside the class | Outside the class |
| Main method | compareTo() | compare() |
| Order count | One natural order | Many custom orders |
| Typical use | Default sort | Ad-hoc sort |
| Java version | Older core API | Very flexible since Java 8 lambdas |
Comparable when the type has one obvious business ordering, like String alphabetically or Integer numerically.Comparator when users can ask for different views, such as by name, by date, by salary, or by priority.Comparator when you do not own the class, because you can still sort it without editing the source.Comparable for a default order that most code will want.Sorting a list is usually O(n log n); the comparison itself should be cheap because it is called many times. For sorted maps and sets, insert/search/delete are typically O(log n). In Java object sorting, List.sort() and Collections.sort() use a stable TimSort implementation, which can use up to O(n) extra space in some cases.
The big gotcha: if two different objects return 0 from compareTo() or compare(), a TreeSet or TreeMap may treat them as duplicates even if equals() says they are different. Also, if you use mutable fields such as name or status in your ordering and then change them after insertion into a sorted collection, the structure can become logically broken.
Real-World Story: Imagine a checkout service that shows urgent orders in a support dashboard. The team gives Order a natural order by priority, then by created time, because that is the default view most operators want. Later, analytics wants a different view by customer name, so the team adds a Comparator instead of changing the class again.
What goes wrong when someone misunderstands the difference? A developer makes compareTo() use only priority, ignoring the unique order id. In a TreeSet-backed queue, two different orders with the same priority are treated as the same item, so one disappears from the dashboard. The symptom is subtle: counts in the UI are lower than the database, logs show fewer inserts than expected, and support agents notice missing urgent orders even though the API returned success.
This is exactly why interviewers care: ordering is not just about pretty sorting on screen. In Java, the ordering rule can affect deduplication, lookup speed, and even whether a record survives insertion into a sorted collection.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.TreeSet;
public class ComparableVsComparatorDemo {
public static void main(String[] args) {
List<Person> people = new ArrayList<>(Arrays.asList(
new Person("Ava", 32, 120_000),
new Person("Ben", 28, 90_000),
new Person("Cara", 32, 150_000),
new Person("Ava", 32, 110_000) // same natural order as the first Ava
));
// Comparable gives the class a default order.
List<Person> naturalOrder = new ArrayList<>(people);
Collections.sort(naturalOrder);
System.out.println("Natural order (Comparable: age, then name):");
naturalOrder.forEach(System.out::println);
// Comparator gives a different, reusable rule without changing Person.
Comparator<Person> bySalaryDescThenName =
Comparator.comparingDouble(Person::salary)
.reversed()
.thenComparing(Person::name);
List<Person> customOrder = new ArrayList<>(people);
customOrder.sort(bySalaryDescThenName);
System.out.println("\nCustom order (Comparator: salary desc, then name):");
customOrder.forEach(System.out::println);
// TreeSet uses ordering to decide both position and uniqueness.
TreeSet<Person> naturalSet = new TreeSet<>();
naturalSet.addAll(people);
System.out.println("\nTreeSet with natural order:");
naturalSet.forEach(System.out::println);
System.out.println("TreeSet size = " + naturalSet.size());
System.out.println("Notice one Ava disappeared because compareTo returned 0 for the same age and name.");
// Edge case: if a sorted collection cannot compare elements, it fails at runtime.
try {
TreeSet<Object> broken = new TreeSet<>();
broken.add(new Object());
broken.add(new Object()); // second insert needs a comparison, but Object has no natural order
} catch (ClassCastException ex) {
System.out.println("\nEdge case: TreeSet without Comparable/Comparator fails:");
System.out.println(ex.getClass().getSimpleName() + ": " + ex.getMessage());
}
}
static final class Person implements Comparable<Person> {
private final String name;
private final int age;
private final double salary;
Person(String name, int age, double salary) {
this.name = name;
this.age = age;
this.salary = salary;
}
String name() {
return name;
}
double salary() {
return salary;
}
@Override
public int compareTo(Person other) {
// Default order: youngest first; if ages tie, sort by name.
int byAge = Integer.compare(this.age, other.age);
if (byAge != 0) {
return byAge;
}
return this.name.compareTo(other.name);
}
@Override
public String toString() {
return name + " | age=" + age + " | salary=" + (long) salary;
}
}
}Follow-up & Tricky Questions:
Comparable.compareTo(). For String, that is lexicographic order; for numbers, it is numeric order.Comparable and still use Comparator? Yes. The class can provide one default order, and callers can still pass a different Comparator whenever they need another view.compareTo() is inconsistent with equals()? Sorted collections may behave strangely: two objects can be considered the same for ordering but not for equality. That can cause surprising drops in TreeSet or key replacement in TreeMap.Comparator often preferred in modern code? It is more flexible and composable. Since Java 8 you can build it with lambdas, comparing, thenComparing, reversed, and null-handling helpers.Collections.sort() require Comparable? Only if you do not pass a comparator. If you pass a Comparator, the list elements do not need to implement Comparable.compareTo() or compare() return any negative or positive number? Yes; only the sign matters. Do not assume it must be -1, 0, or 1.Comparable? Yes, but only if you give the set a Comparator up front. Without one, the failure appears at runtime when a comparison is needed.compareTo(this, other) allowed to use subtraction like a - b? It is risky because integer overflow can flip the sign. Use Integer.compare, Long.compare, or Double.compare instead.compareTo() returns 0, are the objects equal? Not necessarily. It only means they are equal in ordering; equals() may still return false, which is why sorted collections need careful design.TreeSet use equals() to detect duplicates? No, it uses ordering. If the comparator says two values are the same position, the second one is treated as a duplicate.TreeSet<Object> fail without a comparator? Usually not, because no comparison is needed for the very first element. The error often appears on the second insert, when Java finally needs to compare values.Common Mistakes:
Comparable lives in the class; Comparator lives outside the class.compareTo(). Correction: use Integer.compare or similar helpers to avoid overflow.TreeSet/TreeMap. Correction: compare result 0 means “same key” for sorted collections.Memory Hook: Think: Comparable = the object knows its own rank; Comparator = a referee carrying a different rulebook.
Cheat Sheet:
Comparable → compareTo() → one natural order.Comparator → compare() → many custom orders.Comparable is inside the class; Comparator is passed in.Comparator easy with lambdas and chaining.Practice Tasks:
Comparable for a Student class by GPA, then by name.Comparator that sorts students by descending score and handles null names safely.TreeSet and observe how changing the comparison fields changes which items are kept.