The short answer

Comparable lets a class define its own single natural order. You implement compareTo() inside the class, and Collections.sort(list) uses it. Comparator defines an order outside the class. You implement compare() in a separate class or lambda. So you can sort the same objects many ways, and even sort types you cannot edit. In short: Comparable is one built-in order owned by the object. Comparator is any number of custom orders owned by the caller.

Comparator vs Comparable is one of the most common Java interview questions. It trips people up because both interfaces sort objects, and both return a negative, zero, or positive number. The real difference is where the sorting logic lives and how many orders you can have.

Comparable builds the order into the class itself, so every object knows how to compare itself to another. Comparator keeps the order separate, so you can define as many orderings as you need without touching the class. That single design choice explains every other difference below.

This guide defines each interface on its own and compares them point by point. It then shows working code for both, plus the interview questions and FAQs that come up most. Both interfaces are core to the Java Collections framework and to sorting with Collections.sort, List.sort, TreeSet, and TreeMap.

Two-panel diagram showing Comparable with a compareTo method inside the object for a single natural order, against Comparator with separate external compare methods for multiple custom orders in Java
Comparable sorts an object by its own compareTo (one natural order); Comparator defines order externally with compare (many custom orders).<br />

What is the Comparable Interface?

Comparable lives in the java.lang package and declares a single method, compareTo(T o). A class implements Comparable to give its objects a natural order — the one default way they should sort. Because the method sits inside the class, every object can compare itself to another of the same type.

The compareTo() method takes one argument and returns an int:

  • negative — this object comes before the other;
  • zero — the two are equal in order;
  • positive — this object comes after the other.

Once a class implements Comparable, Collections.sort(list) and Arrays.sort(array) sort it with no extra arguments. A TreeSet or TreeMap then uses that order automatically. The catch: a class has only one natural order, and adding it means editing the class itself.

What is the Comparator Interface?

Comparator lives in the java.util package and declares compare(T o1, T o2). You write a Comparator outside the class, in a separate class or a lambda. This lets you define many orders for the same type. It can even sort classes you cannot modify, such as library classes.

The compare() method takes two arguments and returns the same negative, zero, or positive int. You pass a Comparator as the second argument to Collections.sort(list, comparator) or list.sort(comparator).

Comparator is a functional interface, so you can write it as a lambda. Java 8 also added helpers like Comparator.comparing(), thenComparing(), and reversed(), which make multi-field sorting short and readable. See how interfaces fit the wider language in our guide to abstract class vs interface.

Comparator vs Comparable: Key Differences

Infographic comparing the Comparable compareTo method with one argument in java.lang against the Comparator compare method with two arguments in java.util, with a legend for negative, zero and positive return values
compareTo(o) takes one argument; compare(o1, o2) takes two. Negative, zero, positive set the order.<br />
AspectComparableComparator
Packagejava.langjava.util
MethodcompareTo(T o) — one argumentcompare(T o1, T o2) — two arguments
Where it livesInside the class being sortedIn a separate class or a lambda
Order it definesThe single natural orderAny custom order you write
Number of orderingsOne per classAs many as you like
Modifies the class?Yes — the class implements itNo — the class stays untouched
Sort callCollections.sort(list)Collections.sort(list, comparator)
Lambda / functionalConventionally implemented in the classFunctional interface, commonly a lambda
Typical useOne obvious order; TreeSet, TreeMapMany orders, or sorting classes you cannot edit

Code Examples

The snippets below sort the same Student class. First comes its natural order with Comparable, then other orders with Comparator.

Comparable — the class defines its own order:

import java.util.*;

class Student implements Comparable<Student> {
    String name;
    int marks;
    Student(String name, int marks) { this.name = name; this.marks = marks; }

    // Natural order: by marks, ascending
    @Override
    public int compareTo(Student other) {
        return Integer.compare(this.marks, other.marks);
    }
}

List<Student> list = new ArrayList<>(List.of(
        new Student("Asha", 82), new Student("Ravi", 75)));

Collections.sort(list);   // uses compareTo -> sorts by marks

Use Integer.compare(a, b) rather than a - b, because subtraction can overflow for large values.

Comparator — the order lives outside the class:

import java.util.*;

// Sort by name, without touching the Student class
Comparator<Student> byName = (a, b) -> a.name.compareTo(b.name);
Collections.sort(list, byName);

// Java 8+: combine keys, by marks descending then name
list.sort(Comparator.comparingInt((Student s) -> s.marks)
                     .reversed()
                     .thenComparing(s -> s.name));

The Comparable version bakes one order into Student. The Comparator version adds new orders from the outside and never changes the class. That is why it scales to many sort rules. Overriding compareTo or compare is a form of method overriding, one of the building blocks of object-oriented programming.

When to Use Comparator vs Comparable

Use Comparable when a class has one obvious, default order and you own the class. Sorting students by marks, dates by time, or money by amount all fit a single natural order. Comparable then keeps the call simple: Collections.sort(list).

Use Comparator when you need more than one order, or when you cannot edit the class. Sorting the same students by name, then by marks, then by age calls for several comparators. Comparator also wins when the type comes from a library you do not control. You simply add the order from outside.

Comparison infographic listing Comparable properties such as java.lang, compareTo, one natural order against Comparator properties such as java.util, compare, many custom orders and lambda support
Comparator vs Comparable at a glance: package, method, where it lives, and how many orders.<br />

Many real programs use both. A class implements Comparable for its default order, and callers pass a Comparator whenever they need a different one. The two interfaces work together rather than competing.

Interview Questions on Comparator vs Comparable

Both return an int. A negative value means the first object should come before the second, zero means they are equal in order, and a positive value means the first comes after the second. compareTo(o) compares the current object to o, while compare(o1, o2) compares two passed-in objects. The sort uses the sign of the result, not its exact size.

Yes, and it is common. The class implements Comparable to define its natural order, and you write one or more Comparators for the other orders you need. For example, Student can implement compareTo to sort by marks, while a separate Comparator sorts by name. Callers pick whichever order they want at sort time.

Yes. Comparator has one abstract method, compare(), so it is a functional interface and you can write it as a lambda. That keeps sorting concise, as in list.sort((a, b) -> a.name.compareTo(b.name)). Java 8 also added static and default helpers such as Comparator.comparing(), thenComparing(), and reversed() for clean multi-field sorting.

Frequently Asked Questions

Comparable defines a single natural order inside the class using compareTo(o), and Collections.sort(list) uses it. Comparator defines order outside the class using compare(o1, o2), so you can create many orders and sort types you cannot edit. Comparable lives in java.lang and Comparator in java.util.

Comparable is in java.lang, which is imported automatically, so a class can implement it without an import. Comparator is in java.util, so you import java.util.Comparator (or java.util.*) to use it. This split is a common interview detail.

Use Comparator when you need more than one sort order, or when you cannot change the class, such as a class from a third-party library. Use Comparable when the type has one obvious natural order and you own the source. Many programs use both at once.

Yes. Pass a Comparator to Collections.sort(list, comparator) or list.sort(comparator), and the class does not need to implement Comparable at all. With a lambda or Comparator.comparing(), you can sort by any field on the fly without editing the class.

Wrapping Up

The whole comparison rests on one idea: Comparable puts the order inside the object, while Comparator keeps it outside. Comparable gives a class its single natural order through compareTo. Comparator lets callers define any number of custom orders through compare.

So reach for Comparable when there is one clear way to sort and you own the class. Reach for Comparator when you need several orders or cannot touch the class. Used together, they cover every sorting need in Java cleanly.

Related reading on DiffStudy:


Whatsapp-color Created with Sketch.

By Arun Kumar

Full Stack Developer with a BE in Computer Science, working with React, Next.js, Node.js, MongoDB, and AI/ML tools. Founder of DiffStudy — built to help CS students ace GATE and university exams, and keep developers up to date across AI, cloud, system design, web development, and every field of computer science. Every article is written from real hands-on experience, not just theory.

One thought on “Comparator vs Comparable in Java: Key Differences Explained”
  1. Gratias tibi ago pro hoc articulo informativo! Comparator et Comparable interfacia semper me confudunt, sed nunc melius intellego quomodo ea in Java uti possim. Magna est discrimina inter ea recte intellegere. Bene scripsisti!

Leave a Reply

Your email address will not be published. Required fields are marked *


You cannot copy content of this page