0
0
JavaComparisonBeginner · 4 min read

Comparable vs Comparator in Java: Key Differences and Usage

In Java, Comparable is an interface used to define the natural ordering of objects by implementing the compareTo() method within the class itself. Comparator is a separate interface used to define custom orderings by implementing the compare() method externally, allowing multiple sorting strategies.
⚖️

Quick Comparison

This table summarizes the main differences between Comparable and Comparator interfaces in Java.

AspectComparableComparator
PurposeDefines natural ordering inside the classDefines custom ordering outside the class
Method to implementcompareTo(T o)compare(T o1, T o2)
LocationImplemented by the class of objects to be sortedImplemented by a separate class or lambda expression
Number of sort sequencesOnly one natural orderMultiple different orders possible
ModificationRequires modifying the classNo need to modify the class
Java 8+ supportCan use default methodsSupports lambda expressions and method references
⚖️

Key Differences

Comparable is used when a class has a single natural ordering. The class implements the Comparable interface and overrides the compareTo() method to define how objects of that class should be compared. This means the sorting logic is inside the class itself.

On the other hand, Comparator is a separate interface that allows defining multiple ways to compare objects without changing the class. You implement the compare() method in a different class or use lambda expressions to create custom sorting rules. This is useful when you want to sort objects in different ways at different times.

In summary, use Comparable for a default, single sorting order embedded in the class, and use Comparator when you need flexibility to sort objects differently without modifying their class.

⚖️

Code Comparison

Here is an example using Comparable to sort a list of Person objects by their age (natural order):

java
import java.util.*;

class Person implements Comparable<Person> {
    String name;
    int age;

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

    @Override
    public int compareTo(Person other) {
        return Integer.compare(this.age, other.age);
    }

    @Override
    public String toString() {
        return name + "(" + age + ")";
    }
}

public class ComparableExample {
    public static void main(String[] args) {
        List<Person> people = new ArrayList<>();
        people.add(new Person("Alice", 30));
        people.add(new Person("Bob", 25));
        people.add(new Person("Charlie", 35));

        Collections.sort(people);

        System.out.println(people);
    }
}
Output
[Bob(25), Alice(30), Charlie(35)]
↔️

Comparator Equivalent

Here is the same sorting task done using a Comparator to sort Person objects by age without modifying the Person class:

java
import java.util.*;

class Person {
    String name;
    int age;

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

    @Override
    public String toString() {
        return name + "(" + age + ")";
    }
}

public class ComparatorExample {
    public static void main(String[] args) {
        List<Person> people = new ArrayList<>();
        people.add(new Person("Alice", 30));
        people.add(new Person("Bob", 25));
        people.add(new Person("Charlie", 35));

        Comparator<Person> ageComparator = (p1, p2) -> Integer.compare(p1.age, p2.age);

        Collections.sort(people, ageComparator);

        System.out.println(people);
    }
}
Output
[Bob(25), Alice(30), Charlie(35)]
🎯

When to Use Which

Choose Comparable when your class has a clear natural order that makes sense for most uses, and you want to embed this order inside the class itself. This is simpler and makes sorting straightforward.

Choose Comparator when you need multiple ways to sort objects, or when you cannot modify the class (for example, classes from external libraries). Comparator offers flexibility and keeps sorting logic separate.

In practice, use Comparable for default sorting and Comparator for custom or multiple sorting strategies.

Key Takeaways

Use Comparable to define a single natural order inside the class with compareTo().
Use Comparator to create multiple custom orders outside the class with compare().
Comparable requires modifying the class; Comparator does not.
Comparator supports lambda expressions for concise sorting logic.
Choose Comparable for default sorting and Comparator for flexible sorting needs.