Skip to content
  • Comparable vs Comparator · Java

Comparable vs Comparator

LearnViaNotes @learnvianotes· 3 min read

Comparable gives a class its one natural order (compareTo); a Comparator is any number of external orders built fluently with comparing, thenComparing and reversed.

Comparable<T>Comparator<T>
Packagejava.langjava.util
Methodint compareTo(T other)int compare(T a, T b)
WhereInside the class being sortedSeparate object / lambda
How many ordersOne — the natural orderAs many as you like
Used byCollections.sort(list), TreeMap, Arrays.sort with no comparatorlist.sort(cmp), new TreeSet<>(cmp), stream.sorted(cmp)
Examples in the JDKString, Integer, LocalDate, enumsString.CASE_INSENSITIVE_ORDER, Comparator.reverseOrder()

The contract

  • Return negative if this < other, zero if equal, positive if greater — only the sign matters.

  • Antisymmetric: sgn(a.compareTo(b)) == -sgn(b.compareTo(a)); transitive; consistent across calls.

  • Strongly recommended: consistent with equals (compareTo == 0 ⇔ equals) — sorted sets and maps use compareTo for equality.

Natural order with Comparable

Java
import java.util.*;

public class Main {
    public static void main(String[] args) {
        List<Version> vs = new ArrayList<>(List.of(new Version(1, 10), new Version(1, 2), new Version(0, 9)));
        Collections.sort(vs);
        System.out.println(vs);
        System.out.println(Collections.max(vs));
    }
}

record Version(int major, int minor) implements Comparable<Version> {
    @Override
    public int compareTo(Version o) {
        int c = Integer.compare(major, o.major);
        return c != 0 ? c : Integer.compare(minor, o.minor);
    }

    @Override
    public String toString() { return major + "." + minor; }
}
Output
[0.9, 1.2, 1.10]
1.10

Building comparators fluently

Java
import java.util.*;

public class Main {
    record Emp(String name, String dept, int salary) {}

    public static void main(String[] args) {
        List<Emp> staff = new ArrayList<>(List.of(
            new Emp("Ravi", "HR", 50), new Emp("Asha", "Eng", 90),
            new Emp("Meera", "Eng", 70), new Emp("Kiran", "HR", 50)));

        staff.sort(Comparator.comparing(Emp::dept)
                .thenComparing(Emp::salary, Comparator.reverseOrder())
                .thenComparing(Emp::name));
        staff.forEach(e -> System.out.println(e.dept() + " " + e.salary() + " " + e.name()));

        List<String> words = new ArrayList<>(List.of("pear", "Fig", "apple", "kiwi"));
        words.sort(Comparator.comparingInt(String::length).reversed());
        System.out.println(words);
        words.sort(String.CASE_INSENSITIVE_ORDER);
        System.out.println(words);

        List<String> withNull = new ArrayList<>(Arrays.asList("b", null, "a"));
        withNull.sort(Comparator.nullsFirst(Comparator.naturalOrder()));
        System.out.println(withNull);
    }
}
Output
Eng 90 Asha
Eng 70 Meera
HR 50 Kiran
HR 50 Ravi
[apple, pear, kiwi, Fig]
[apple, Fig, kiwi, pear]
[null, a, b]
Factory / methodMeaning
Comparator.comparing(keyFn)Compare by an extracted Comparable key
comparingInt/Long/Double(fn)Same, without boxing
.thenComparing(...)Tie-breaker
.reversed()Flip the whole chain built so far
Comparator.naturalOrder() / reverseOrder()Natural order / its reverse
nullsFirst(cmp) / nullsLast(cmp)Treat null as smallest / largest

Trap: comparing by subtraction

Java
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Comparator<Integer> bad = (a, b) -> a - b;          // overflows for far-apart values
        Comparator<Integer> good = Integer::compare;
        int big = Integer.MAX_VALUE, small = -1;
        System.out.println("a - b says: " + bad.compare(big, small));
        System.out.println("compare says: " + good.compare(big, small));

        List<Integer> xs = new ArrayList<>(List.of(Integer.MIN_VALUE, 1));
        xs.sort(bad);                                       // 1 - MIN_VALUE overflows to negative
        System.out.println(xs);
    }
}
Output
a - b says: -2147483648
compare says: 1
[1, -2147483648]

Comparable vs Comparator — when to use which?

What happens if compareTo is inconsistent with equals?

How does reversed() behave in a chain?

Free for students and teachers

Write notes like this one

Cards for every idea, quizzes and flashcards, read aloud — on the web and your phone.

Something wrong with this note? Open it to report