Comparable vs Comparator in Java: Explained with Examples

In this tutorial, you’ll learn the difference between Comparable and Comparator in Java. We’ll explore how sorting works in Java Collections, how to use both interfaces to define custom sorting logic, and when to use which one in real-world applications.


1. Why Do We Need Comparable and Comparator?

Java provides these interfaces to sort user-defined objects (like Employee, Student, etc.). When you try to sort objects of your own class using Collections.sort() or Arrays.sort(), Java doesn’t know how to compare them — so you must define the comparison logic.

  • Comparable → Used to define default sorting logic inside a class.
  • Comparator → Used to define multiple or external sorting logics outside the class.

2. What is Comparable?

The Comparable interface is found in java.lang package and defines a single method:


public interface Comparable<T> {
    int compareTo(T obj);
}
  • It defines a **natural ordering** for objects.
  • Returns a negative number if this < obj, zero if equal, and a positive number if this > obj.

Example: Sorting Students by Roll Number (Natural Order)


class Student implements Comparable<Student> {
    int rollNo;
    String name;

    Student(int rollNo, String name) {
        this.rollNo = rollNo;
        this.name = name;
    }

    @Override
    public int compareTo(Student s) {
        return this.rollNo - s.rollNo; // ascending order
    }

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

public class ComparableExample {
    public static void main(String[] args) {
        List<Student> list = new ArrayList<>();
        list.add(new Student(103, "Ravi"));
        list.add(new Student(101, "Aman"));
        list.add(new Student(102, "Neha"));

        Collections.sort(list); // uses compareTo() method
        System.out.println(list);
    }
}

Output: [101 - Aman, 102 - Neha, 103 - Ravi]


3. What is Comparator?

The Comparator interface is found in java.util package and is used when you want multiple or custom sorting logic.


public interface Comparator<T> {
    int compare(T obj1, T obj2);
}
  • Defines custom sorting logic externally (outside the class).
  • Allows multiple sorting strategies for the same class.

Example: Sorting Students by Name (Using Comparator)


class Student {
    int rollNo;
    String name;

    Student(int rollNo, String name) {
        this.rollNo = rollNo;
        this.name = name;
    }

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

class SortByName implements Comparator<Student> {
    public int compare(Student s1, Student s2) {
        return s1.name.compareTo(s2.name);
    }
}

public class ComparatorExample {
    public static void main(String[] args) {
        List<Student> list = new ArrayList<>();
        list.add(new Student(103, "Ravi"));
        list.add(new Student(101, "Aman"));
        list.add(new Student(102, "Neha"));

        Collections.sort(list, new SortByName()); // custom sorting by name
        System.out.println(list);
    }
}

Output: [101 - Aman, 102 - Neha, 103 - Ravi]


4. Comparable vs Comparator (Key Differences)

FeatureComparableComparator
Packagejava.langjava.util
MethodcompareTo()compare()
Sorting Logic LocationInside the classOutside the class
Number of Sorting LogicsOnly one (natural order)Multiple custom logics possible
Used ByCollections.sort() and Arrays.sort()Collections.sort(list, comparator)
Example UseSort by roll numberSort by name, marks, etc.

5. Real-World Example: Employee Sorting in HR Application


class Employee implements Comparable<Employee> {
    int id;
    String name;
    double salary;

    Employee(int id, String name, double salary) {
        this.id = id;
        this.name = name;
        this.salary = salary;
    }

    @Override
    public int compareTo(Employee e) {
        return this.id - e.id; // natural order by ID
    }

    @Override
    public String toString() {
        return id + " - " + name + " - " + salary;
    }
}

class SortBySalary implements Comparator<Employee> {
    public int compare(Employee e1, Employee e2) {
        return Double.compare(e1.salary, e2.salary);
    }
}

class SortByName implements Comparator<Employee> {
    public int compare(Employee e1, Employee e2) {
        return e1.name.compareTo(e2.name);
    }
}

public class EmployeeSorting {
    public static void main(String[] args) {
        List<Employee> employees = new ArrayList<>();
        employees.add(new Employee(103, "Ravi", 60000));
        employees.add(new Employee(101, "Aman", 55000));
        employees.add(new Employee(102, "Neha", 70000));

        System.out.println("Sort by ID (Comparable):");
        Collections.sort(employees);
        System.out.println(employees);

        System.out.println("\nSort by Salary (Comparator):");
        Collections.sort(employees, new SortBySalary());
        System.out.println(employees);

        System.out.println("\nSort by Name (Comparator):");
        Collections.sort(employees, new SortByName());
        System.out.println(employees);
    }
}

Output:


Sort by ID (Comparable):
[101 - Aman - 55000.0, 102 - Neha - 70000.0, 103 - Ravi - 60000.0]

Sort by Salary (Comparator):
[101 - Aman - 55000.0, 103 - Ravi - 60000.0, 102 - Neha - 70000.0]

Sort by Name (Comparator):
[101 - Aman - 55000.0, 102 - Neha - 70000.0, 103 - Ravi - 60000.0]

6. Comparator Using Lambda Expression (Java 8+)

From Java 8 onward, you can use lambda expressions to make sorting cleaner and shorter.


Collections.sort(employees, (e1, e2) -> e1.name.compareTo(e2.name));
Or even shorter using the built-in Comparator.comparing():

employees.sort(Comparator.comparing(Employee::getName));

7. Interview Questions on Comparable and Comparator

  1. What is the difference between Comparable and Comparator?
    Comparable defines natural sorting inside the class; Comparator defines custom sorting outside the class.
  2. Which package contains these interfaces?
    Comparable → java.lang, Comparator → java.util
  3. How many sorting logics can you define with Comparable?
    Only one (inside the class).
  4. Can we use both Comparable and Comparator together?
    Yes, Comparable can define default sorting, Comparator can override it.
  5. What will happen if compareTo() returns 0?
    The objects are considered equal in sorting order.
  6. Can you sort a list without modifying the class?
    Yes, using Comparator (external sorting).
  7. What is the return type of compare() and compareTo()?
    Both return int.
  8. What is Comparator.comparing()?
    A Java 8 method to simplify Comparator creation using method references.
  9. What happens if two objects are equal in compareTo()?
    They maintain their existing order (stable sort).
  10. Which one provides more flexibility?
    Comparator provides more flexibility because you can define multiple sorting criteria.

8. Summary Table

AspectComparableComparator
LocationInside the classOutside the class
MethodcompareTo(Object o)compare(Object o1, Object o2)
Packagejava.langjava.util
Number of Sort LogicOneMultiple
Used ByCollections.sort(list)Collections.sort(list, comparator)
FlexibilityLessMore

Conclusion

✅ Use Comparable when you want to define a single, natural sorting order within your class (like sorting students by roll number). ✅ Use Comparator when you want to sort objects in multiple different ways (like sorting employees by name, salary, or age).

By mastering these interfaces, you can handle any sorting requirement efficiently in your real-world Java applications.

Next Step: Learn about Streams and Comparator.comparing() in Java 8 for advanced, functional sorting.