Chaining Comparators

thenComparing, reversed and nulls

Example

Sort by department, then by salary descending, then by name. Comparators compose like building blocks.

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

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

    public static void main(String[] args) {
        List<Emp> emps = new ArrayList<>(List.of(
                new Emp("Ravi", "IT", 70000),
                new Emp("Asha", "HR", 50000),
                new Emp("Kiran", "IT", 90000),
                new Emp("Meena", "IT", 70000),
                new Emp("John", "HR", 65000)));

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

        String[] names = { "Zoya", null, "amit", "Bala" };
        Arrays.sort(names, Comparator.nullsLast(String.CASE_INSENSITIVE_ORDER));
        System.out.println(Arrays.toString(names));
        Arrays.sort(names, Comparator.nullsFirst(Comparator.<String>naturalOrder().reversed()));
        System.out.println(Arrays.toString(names));
    }
}

Output

HR 65000 John
HR 50000 Asha
IT 90000 Kiran
IT 70000 Meena
IT 70000 Ravi
[amit, Bala, Zoya, null]
[null, amit, Zoya, Bala]

Cheat Sheet

MethodEffect
Comparator.comparing(keyFn)compare by a key
comparingInt / comparingDoublesame, avoids boxing
.thenComparing(...)tie-breaker
.reversed()reverse the whole comparator
Comparator.reverseOrder()reverse natural order
Comparator.nullsFirst/nullsLast(cmp)handle null safely
String.CASE_INSENSITIVE_ORDERignore case for strings