Detailed explanation
Comparable and Comparator are Java interfaces that define how objects are ordered. Comparable<T>, from java.lang, gives a class its natural ordering through int compareTo(T other). The class itself implements this interface, so ordering becomes part of its public contract. For example, a Person class might choose age as its natural order, while String uses lexicographic ordering. Collections.sort(list) and list.sort(null) use the elements’ natural ordering and therefore require mutually comparable elements.
Comparator<T>, from java.util, represents a separate ordering strategy through int compare(T first, T second). It can be implemented in a separate class, an anonymous class, or a lambda, and it does not require the compared class to implement Comparable. For example, list.sort(Comparator.comparing(Person::getName)) sorts people by name, assuming getName() returns a String. Comparator.comparingInt(Person::getAge) sorts by age, and thenComparing(Person::getName) adds a name-based tie-breaker. A supplied comparator determines the order for that operation instead of the elements’ natural ordering.
Both methods return a negative integer when the first object comes before the second, zero when their ordering positions are equivalent, and a positive integer when the first comes after the second. Sorting algorithms repeatedly invoke these comparisons to arrange elements; TreeSet and TreeMap use them to navigate their tree structure. Implementations must obey the comparison contract, including sign symmetry and transitivity. Avoid return this.age - other.age because integer overflow can produce an incorrect sign; use Integer.compare(this.age, other.age). Comparisons should also remain stable while objects are stored in sorted collections.
In an interview, explain the design choice rather than only naming the methods: use Comparable for one meaningful default order and Comparator for alternate orders, classes you cannot modify, or operation-specific rules. Also discuss consistency with equals. TreeSet treats objects that compare as zero as the same element, and TreeMap treats such keys as equivalent, even if equals returns false. Finally, natural-order comparisons normally reject null, whereas Comparator.nullsFirst or Comparator.nullsLast can explicitly define null placement.
Key points to remember
- Comparable<T> defines natural ordering inside the class using compareTo(T other).
- Comparator<T> defines a separate ordering strategy using compare(T first, T second).
- A supplied Comparator controls that sort operation, even when elements implement Comparable.
- Comparison results indicate negative, zero, or positive ordering; they need not be exactly -1, 0, or 1.
- Use Integer.compare, comparator factories, and thenComparing for safe, readable comparison logic.
Common mistakes candidates make
- Subtracting integer fields in compareTo or compare, which can overflow and reverse the intended ordering.
- Assuming a comparison result of zero always means equals returns true, overlooking TreeSet and TreeMap behaviour.
- Implementing comparisons that violate transitivity or changing ordering fields while objects are stored in sorted collections.
Likely follow-up questions
Can a class use both Comparable and Comparator?
Yes, a class can implement Comparable for its natural order while separate comparators provide alternative orders. For example, Person could naturally sort by age but be sorted by name when a name comparator is supplied.
How do you sort by multiple fields or reverse an order?
Use Comparator.comparingInt(Person::getAge).thenComparing(Person::getName) to sort by age and then name. Calling reversed() on the completed comparator reverses the entire ordering, whereas reversing only one component changes only that component’s direction.
What happens if comparison is inconsistent with equals?
TreeSet may reject a distinct object when it compares as zero to an existing element, and TreeMap may replace the value associated with an equivalent key. BigDecimal illustrates this distinction: 4.0 and 4.00 compare as zero but are not equal according to equals.
Interview tip: Start with natural ordering versus an external strategy, show one example of each, and finish with the subtraction-overflow and sorted-collection caveats.
