Comparable vs Comparator

⭐ Interview Importance: MEDIUM
⏱️ Revision Time: 5 min

TL;DR

  • Comparable: An interface implemented by the class itself to define its default, “natural” sorting order. Uses compareTo().
  • Comparator: A separate class/lambda used to define multiple custom sorting algorithms without modifying the original class. Uses compare().

Concept

Collections like TreeSet or algorithms like Collections.sort() need to know how to order objects. If you ask Java to sort a list of Person objects, it doesn’t know if it should sort by age, name, or height.

1. java.lang.Comparable (Natural Order)

You make the Person class implement Comparable<Person>. You override compareTo(Person other). This is the one true “default” way to sort a Person.

  • Return < 0: this object comes first.
  • Return > 0: other object comes first.
  • Return 0: They are equal.

2. java.util.Comparator (Custom Order)

What if you want to sort by age normally, but sometimes by name? You create a Comparator. A Comparator is an external strategy passed directly into the sorting method (e.g., Collections.sort(list, nameComparator)).

Examples

import java.util.*;

// Implementing Comparable (Default sorting by age)
class Employee implements Comparable<Employee> {
    String name;
    int age;

    public Employee(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public int compareTo(Employee other) {
        return Integer.compare(this.age, other.age); 
    }
    
    @Override
    public String toString() { return name + ":" + age; }
}

public class SortExample {
    public static void main(String[] args) {
        List<Employee> list = new ArrayList<>(Arrays.asList(
            new Employee("Zach", 30),
            new Employee("Alice", 25)
        ));

        // Uses Comparable (Natural Order -> Age)
        Collections.sort(list);
        System.out.println(list); // [Alice:25, Zach:30]

        // Uses Comparator (Custom Order -> Name)
        Comparator<Employee> nameSorter = (e1, e2) -> e1.name.compareTo(e2.name);
        list.sort(nameSorter);
        System.out.println(list); // [Alice:25, Zach:30]
    }
}

Interview Questions

Q: When would you use a Comparator over Comparable?
A: 1. When you don’t have access to the source code of the class (e.g., a third-party library class) to implement Comparable.
2. When you need to sort the objects in multiple different ways (e.g., sort products by price, then later sort them by rating). Comparable only allows one default sorting logic.

Q: In Java 8+, how can you chain comparators easily?
A: The Comparator interface introduced default and static methods like comparing() and thenComparing(). You can easily sort by multiple fields without writing verbose logic:
list.sort(Comparator.comparing(Employee::getAge).thenComparing(Employee::getName));