Java : Comparator with Examples

Comparator (Java SE 19 & JDK 19) API Examples.
You will find code examples on most Comparator methods.


Summary

A comparison function, which imposes a total ordering on some collection of objects. Comparators can be passed to a sort method (such as Collections.sort or Arrays.sort) to allow precise control over the sort order.

Class diagram

See also : Comparable

record Sample(String text, int num) {
    @Override
    public String toString() {
        return "(%s, %d)".formatted(text, num);
    }
}

final var comparator = new Comparator<Sample>() {
    @Override
    public int compare(Sample o1, Sample o2) {
        // Compare with text and num.
        if (!o1.text().equals(o2.text())) {
            return o1.text().compareTo(o2.text());
        } else {
            return o1.num() - o2.num();
        }
    }
};

final var list = List.of(
        new Sample("bbb", 2), new Sample("bbb", 3), new Sample("bbb", 1),
        new Sample("aaa", 3), new Sample("aaa", 1), new Sample("aaa", 2));

final var sorted = list.stream().sorted(comparator).toList();

System.out.println(list); // [(bbb, 2), (bbb, 3), (bbb, 1), (aaa, 3), (aaa, 1), (aaa, 2)]
System.out.println(sorted); // [(aaa, 1), (aaa, 2), (aaa, 3), (bbb, 1), (bbb, 2), (bbb, 3)]

Methods

int compare (T o1, T o2)

Compares its two arguments for order.

Please see the code example in the summary.

static <T, U extends Comparable<? super U>> Comparator<T> comparing (Function<? super T,? extends U> keyExtractor)

Accepts a function that extracts a Comparable sort key from a type T, and returns a Comparator<T> that compares by that sort key.

record Sample(String textA, String textB) {
    @Override
    public String toString() {
        return "(%s, %s)".formatted(textA, textB);
    }
}

final var list = List.of(
        new Sample("ddd", "W"), new Sample("ccc", "X"),
        new Sample("bbb", "Z"), new Sample("aaa", "Y"));

System.out.println(list); // [(ddd, W), (ccc, X), (bbb, Z), (aaa, Y)]

{
    final var keyExtractor = new Function<Sample, String>() {
        @Override
        public String apply(Sample sample) {
            return sample.textA();
        }
    };

    final var comparator = Comparator.comparing(keyExtractor);
    final var sorted = list.stream().sorted(comparator).toList();

    System.out.println(sorted); // [(aaa, Y), (bbb, Z), (ccc, X), (ddd, W)]
}

{
    final var comparator = Comparator.comparing(Sample::textB);
    final var sorted = list.stream().sorted(comparator).toList();

    System.out.println(sorted); // [(ddd, W), (ccc, X), (aaa, Y), (bbb, Z)]
}

static <T, U> Comparator<T> comparing (Function<? super T,? extends U> keyExtractor, Comparator<? super U> keyComparator)

Accepts a function that extracts a sort key from a type T, and returns a Comparator<T> that compares by that sort key using the specified Comparator.

record Sample(String text, int num) {
    @Override
    public String toString() {
        return "(%s, %d)".formatted(text, num);
    }
}

final var list = List.of(
        new Sample("ccc", 2), new Sample("DDD", 1),
        new Sample("aaa", 4), new Sample("BBB", 3));

System.out.println(list); // [(ccc, 2), (DDD, 1), (aaa, 4), (BBB, 3)]

{
    final var comparator = Comparator.comparing(Sample::text, String.CASE_INSENSITIVE_ORDER);
    final var sorted = list.stream().sorted(comparator).toList();

    System.out.println(sorted); // [(aaa, 4), (BBB, 3), (ccc, 2), (DDD, 1)]
}

{
    final var comparator = Comparator.comparing(Sample::text);
    final var sorted = list.stream().sorted(comparator).toList();

    System.out.println(sorted); // [(BBB, 3), (DDD, 1), (aaa, 4), (ccc, 2)]
}

static <T> Comparator<T> comparingDouble (ToDoubleFunction<? super T> keyExtractor)

Accepts a function that extracts a double sort key from a type T, and returns a Comparator<T> that compares by that sort key.

record Sample(double num, String text) {
    @Override
    public String toString() {
        return "(%.1f, %s)".formatted(num, text);
    }
}

final var list = List.of(
        new Sample(2.0, "ccc"), new Sample(3.0, "bbb"),
        new Sample(4.0, "aaa"), new Sample(1.0, "ddd"));

System.out.println(list); // [(2.0, ccc), (3.0, bbb), (4.0, aaa), (1.0, ddd)]

final var comparator = Comparator.comparingDouble(Sample::num);
final var sorted = list.stream().sorted(comparator).toList();

System.out.println(sorted); // [(1.0, ddd), (2.0, ccc), (3.0, bbb), (4.0, aaa)]

static <T> Comparator<T> comparingInt (ToIntFunction<? super T> keyExtractor)

Accepts a function that extracts an int sort key from a type T, and returns a Comparator<T> that compares by that sort key.

record Sample(int num, String text) {
    @Override
    public String toString() {
        return "(%d, %s)".formatted(num, text);
    }
}

final var list = List.of(
        new Sample(2, "ccc"), new Sample(3, "bbb"),
        new Sample(4, "aaa"), new Sample(1, "ddd"));

System.out.println(list); // [(2, ccc), (3, bbb), (4, aaa), (1, ddd)]

final var comparator = Comparator.comparingInt(Sample::num);
final var sorted = list.stream().sorted(comparator).toList();

System.out.println(sorted); // [(1, ddd), (2, ccc), (3, bbb), (4, aaa)]

static <T> Comparator<T> comparingLong (ToLongFunction<? super T> keyExtractor)

Accepts a function that extracts a long sort key from a type T, and returns a Comparator<T> that compares by that sort key.

record Sample(long num, String text) {
    @Override
    public String toString() {
        return "(%d, %s)".formatted(num, text);
    }
}

final var list = List.of(
        new Sample(20000000000L, "ccc"), new Sample(30000000000L, "bbb"),
        new Sample(40000000000L, "aaa"), new Sample(10000000000L, "ddd"));

// [(20000000000, ccc), (30000000000, bbb), (40000000000, aaa), (10000000000, ddd)]
System.out.println(list);

final var comparator = Comparator.comparingLong(Sample::num);
final var sorted = list.stream().sorted(comparator).toList();

// [(10000000000, ddd), (20000000000, ccc), (30000000000, bbb), (40000000000, aaa)]
System.out.println(sorted);

boolean equals (Object obj)

Indicates whether some other object is "equal to" this comparator.

API spec says "Note that it is always safe not to override Object.equals(Object)." Therefore, the code example is omitted.

static <T extends Comparable<? super T>> Comparator<T> naturalOrder ()

Returns a comparator that compares Comparable objects in natural order.

final var comparator = Comparator.<String>naturalOrder();

final var list = List.of("ccc", "ddd", "aaa", "bbb");
final var sorted = list.stream().sorted(comparator).toList();

System.out.println(list); // [ccc, ddd, aaa, bbb]
System.out.println(sorted); // [aaa, bbb, ccc, ddd]

static <T> Comparator<T> nullsFirst (Comparator<? super T> comparator)

Returns a null-friendly comparator that considers null to be less than non-null.

final var list = new ArrayList<String>();
list.add("ccc");
list.add("ddd");
list.add(null);
list.add("aaa");
list.add("bbb");

System.out.println(list); // [ccc, ddd, null, aaa, bbb]

final var comparator = Comparator.<String>naturalOrder();

{
    final var nullsFirstComparator = Comparator.nullsFirst(comparator);
    final var sorted = list.stream().sorted(nullsFirstComparator).toList();

    System.out.println(sorted); // [null, aaa, bbb, ccc, ddd]
}

{
    final var nullsLastComparator = Comparator.nullsLast(comparator);
    final var sorted = list.stream().sorted(nullsLastComparator).toList();

    System.out.println(sorted); // [aaa, bbb, ccc, ddd, null]
}

{
    try {
        final var sorted = list.stream().sorted(comparator).toList();
    } catch (NullPointerException e) {
        System.out.println("NullPointerException!");
    }

    // Result
    // ↓
    //NullPointerException!
}

static <T> Comparator<T> nullsLast (Comparator<? super T> comparator)

Returns a null-friendly comparator that considers null to be greater than non-null.

Please see nullsFirst(Comparator<? super T> comparator).

default Comparator<T> reversed ()

Returns a comparator that imposes the reverse ordering of this comparator.

final var comparator = Comparator.<String>naturalOrder();
final var reversedComparator = comparator.reversed();

final var list = List.of("ccc", "ddd", "aaa", "bbb");
System.out.println(list); // [ccc, ddd, aaa, bbb]

final var sorted = list.stream().sorted(comparator).toList();
final var reversedSorted = list.stream().sorted(reversedComparator).toList();

System.out.println(sorted); // [aaa, bbb, ccc, ddd]
System.out.println(reversedSorted); // [ddd, ccc, bbb, aaa]

static <T extends Comparable<? super T>> Comparator<T> reverseOrder ()

Returns a comparator that imposes the reverse of the natural ordering.

final var comparator = Comparator.<String>reverseOrder();

final var list = List.of("ccc", "ddd", "aaa", "bbb");
final var sorted = list.stream().sorted(comparator).toList();

System.out.println(list); // [ccc, ddd, aaa, bbb]
System.out.println(sorted); // [ddd, ccc, bbb, aaa]

default Comparator<T> thenComparing (Comparator<? super T> other)

Returns a lexicographic-order comparator with another comparator.

final var list = List.of("aaa", "bbb", "ccc", "b", "c", "a", "cc", "aa", "bb");
System.out.println(list); // [aaa, bbb, ccc, b, c, a, cc, aa, bb]

// Sort by natural order.
final var naturalComparator = Comparator.<String>naturalOrder();
final var naturalSorted = list.stream().sorted(naturalComparator).toList();
System.out.println(naturalSorted); // [a, aa, aaa, b, bb, bbb, c, cc, ccc]

// Sort by string length.
final var lengthComparator = Comparator.comparingInt(String::length);
final var lengthSorted = list.stream().sorted(lengthComparator).toList();
System.out.println(lengthSorted); // [b, c, a, cc, aa, bb, aaa, bbb, ccc]

// Sort by string length and natural order.
final var comparator = lengthComparator.thenComparing(naturalComparator);
final var sorted = list.stream().sorted(comparator).toList();
System.out.println(sorted); // [a, b, c, aa, bb, cc, aaa, bbb, ccc]

default <U extends Comparable<? super U>> Comparator<T> thenComparing (Function<? super T,? extends U> keyExtractor)

Returns a lexicographic-order comparator with a function that extracts a Comparable sort key.

record Sample(int num, String text) {
    @Override
    public String toString() {
        return "(%d, %s)".formatted(num, text);
    }
}

final var list = List.of(
        new Sample(2, "ccc"), new Sample(2, "BBB"), new Sample(2, "aaa"),
        new Sample(1, "bbb"), new Sample(1, "CCC"), new Sample(1, "AAA"));

// [(2, ccc), (2, BBB), (2, aaa), (1, bbb), (1, CCC), (1, AAA)]
System.out.println(list);

final var numComparator = Comparator.comparing(Sample::num);
final var numSorted = list.stream().sorted(numComparator).toList();

// [(1, bbb), (1, CCC), (1, AAA), (2, ccc), (2, BBB), (2, aaa)]
System.out.println(numSorted);

{
    final var comparator = numComparator.thenComparing(Sample::text);
    final var sorted = list.stream().sorted(comparator).toList();

    // [(1, AAA), (1, CCC), (1, bbb), (2, BBB), (2, aaa), (2, ccc)]
    System.out.println(sorted);
}

{
    final var comparator = numComparator.thenComparing(Sample::text, String.CASE_INSENSITIVE_ORDER);
    final var sorted = list.stream().sorted(comparator).toList();

    // [(1, AAA), (1, bbb), (1, CCC), (2, aaa), (2, BBB), (2, ccc)]
    System.out.println(sorted);
}

default <U> Comparator<T> thenComparing (Function<? super T,? extends U> keyExtractor, Comparator<? super U> keyComparator)

Returns a lexicographic-order comparator with a function that extracts a key to be compared with the given Comparator.

Please see thenComparing(Function<? super T,? extends U> keyExtractor).

default Comparator<T> thenComparingDouble (ToDoubleFunction<? super T> keyExtractor)

Returns a lexicographic-order comparator with a function that extracts a double sort key.

record Sample(String text, double num) {
    @Override
    public String toString() {
        return "(%s, %.1f)".formatted(text, num);
    }
}

final var list = List.of(
        new Sample("bbb", 2.0), new Sample("bbb", 3.0), new Sample("bbb", 1.0),
        new Sample("aaa", 3.0), new Sample("aaa", 1.0), new Sample("aaa", 2.0));

// [(bbb, 2.0), (bbb, 3.0), (bbb, 1.0), (aaa, 3.0), (aaa, 1.0), (aaa, 2.0)]
System.out.println(list);

final var textComparator = Comparator.comparing(Sample::text);
final var textSorted = list.stream().sorted(textComparator).toList();

// [(aaa, 3.0), (aaa, 1.0), (aaa, 2.0), (bbb, 2.0), (bbb, 3.0), (bbb, 1.0)]
System.out.println(textSorted);

final var comparator = textComparator.thenComparingDouble(Sample::num);
final var sorted = list.stream().sorted(comparator).toList();

// [(aaa, 1.0), (aaa, 2.0), (aaa, 3.0), (bbb, 1.0), (bbb, 2.0), (bbb, 3.0)]
System.out.println(sorted);

default Comparator<T> thenComparingInt (ToIntFunction<? super T> keyExtractor)

Returns a lexicographic-order comparator with a function that extracts an int sort key.

record Sample(String text, int num) {
    @Override
    public String toString() {
        return "(%s, %d)".formatted(text, num);
    }
}

final var list = List.of(
        new Sample("bbb", 2), new Sample("bbb", 3), new Sample("bbb", 1),
        new Sample("aaa", 3), new Sample("aaa", 1), new Sample("aaa", 2));

// [(bbb, 2), (bbb, 3), (bbb, 1), (aaa, 3), (aaa, 1), (aaa, 2)]
System.out.println(list);

final var textComparator = Comparator.comparing(Sample::text);
final var textSorted = list.stream().sorted(textComparator).toList();

// [(aaa, 3), (aaa, 1), (aaa, 2), (bbb, 2), (bbb, 3), (bbb, 1)]
System.out.println(textSorted);

final var comparator = textComparator.thenComparingInt(Sample::num);
final var sorted = list.stream().sorted(comparator).toList();

// [(aaa, 1), (aaa, 2), (aaa, 3), (bbb, 1), (bbb, 2), (bbb, 3)]
System.out.println(sorted);

default Comparator<T> thenComparingLong (ToLongFunction<? super T> keyExtractor)

Returns a lexicographic-order comparator with a function that extracts a long sort key.

record Sample(String text, long num) {
    @Override
    public String toString() {
        return "(%s, %d)".formatted(text, num);
    }
}

final var list = List.of(
        new Sample("bbb", 2), new Sample("bbb", 3), new Sample("bbb", 1),
        new Sample("aaa", 3), new Sample("aaa", 1), new Sample("aaa", 2));

// [(bbb, 2), (bbb, 3), (bbb, 1), (aaa, 3), (aaa, 1), (aaa, 2)]
System.out.println(list);

final var textComparator = Comparator.comparing(Sample::text);
final var textSorted = list.stream().sorted(textComparator).toList();

// [(aaa, 3), (aaa, 1), (aaa, 2), (bbb, 2), (bbb, 3), (bbb, 1)]
System.out.println(textSorted);

final var comparator = textComparator.thenComparingLong(Sample::num);
final var sorted = list.stream().sorted(comparator).toList();

// [(aaa, 1), (aaa, 2), (aaa, 3), (bbb, 1), (bbb, 2), (bbb, 3)]
System.out.println(sorted);

Related posts

Collection

Stream

To top of page