Java Academy · Les

Sorteren op meerdere sleutels met thenComparing

Koppel comparators met thenComparing om op meerdere velden te sorteren volgens een prioriteitsvolgorde.

Les 3 van 414 stappen

Sorteren op meerdere sleutels met thenComparing is een gratis Java Academy-les op CoddyKit. Dit is les 3 van 4. Je kunt de volledige les hieronder gratis lezen en daarna in de browser praktisch oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is. Deze les maakt deel uit van het leertraject Java Academy. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus Java Academy bevat in totaal 4 lessen.

Sorteren op meerdere sleutels

thenComparing() ketent comparators om op meerdere velden te sorteren. Eerst wordt primair gesorteerd; bij gelijkheid volgt de secundaire sortering, enzovoort.

Basisgebruik van thenComparing

Gebruik thenComparing() om gelijke resultaten van de primaire comparator verder te ordenen.

import java.util.*;

record Student(String name, int grade, double gpa) {}

List<Student> students = List.of(
    new Student("Alice",   10, 3.9),
    new Student("Bob",     11, 3.7),
    new Student("Charlie", 10, 3.8),
    new Student("Diana",   11, 3.7)
);

Comparator<Student> sort = Comparator.comparingInt(Student::grade)
    .thenComparingDouble(Student::gpa).reversed()
    .thenComparing(Student::name);

students.stream().sorted(sort).forEach(System.out::println);

Sorteren op drie niveaus

Keten zoveel niveaus met thenComparing als nodig is.

record Employee(String dept, String team, String name, double salary) {}

List<Employee> employees = List.of(
    new Employee("Eng", "Backend", "Alice",   95000),
    new Employee("Eng", "Backend", "Bob",     92000),
    new Employee("Eng", "Frontend","Charlie", 88000),
    new Employee("Mkt", "Growth",  "Diana",   75000)
);

Comparator<Employee> sort = Comparator
    .comparing(Employee::dept)
    .thenComparing(Employee::team)
    .thenComparing(Comparator.comparingDouble(Employee::salary).reversed());

employees.stream().sorted(sort)
    .forEach(e -> System.out.printf("%s > %s > %s: $%.0f%n",
        e.dept(), e.team(), e.name(), e.salary()));

thenComparing met Comparator

Gebruik de variant die een Comparator accepteert wanneer je voor secundaire sleutels een omgekeerde of aangepaste ordening nodig hebt.

Comparator<Employee> sort = Comparator
    .comparing(Employee::dept)
    .thenComparing(Comparator.comparing(Employee::salary).reversed()); // highest paid first
    // equivalent: .thenComparingDouble(Employee::salary, Comparator.reverseOrder())

Sorteren met null-velden

Combineer thenComparing met nullsLast/nullsFirst om optionele velden netjes te verwerken.

record Product(String name, String category, Double rating) {}

Comparator<Product> sort = Comparator
    .comparing(Product::category, Comparator.nullsLast(Comparator.naturalOrder()))
    .thenComparing(Product::rating,  Comparator.nullsLast(Comparator.reverseOrder()))
    .thenComparing(Product::name);

Dynamisch een sorteersleutel kiezen

Selecteer tijdens de uitvoering de sorteersleutel op basis van de voorkeur van de gebruiker.

static Comparator<Product> sortBy(String key) {
    return switch (key) {
        case "price"    -> Comparator.comparingDouble(Product::price);
        case "name"     -> Comparator.comparing(Product::name);
        case "stock"    -> Comparator.comparingInt(Product::stock).reversed();
        default         -> Comparator.comparingDouble(Product::price);
    };
}

String userChoice = "stock";
products.stream().sorted(sortBy(userChoice)).forEach(System.out::println);

thenComparing met een extractfunctie

De variant thenComparing(Function<T,U>) haalt een Comparable-sleutel op voor de secundaire sortering, zonder dat je een expliciete Comparator nodig hebt.

record Event(String type, int year, int month, int day) {}

Comparator<Event> chronological = Comparator
    .comparing(Event::type)
    .thenComparingInt(Event::year)
    .thenComparingInt(Event::month)
    .thenComparingInt(Event::day);

Collecties van records sorteren

Records met accessormethoden werken naadloos met methodeverwijzingen in comparator-ketens.

record Order(String customerId, String status, double total, java.time.LocalDate date) {}

List<Order> orders = loadOrders();

Comparator<Order> byCustomerThenDate = Comparator
    .comparing(Order::customerId)
    .thenComparing(Order::date, Comparator.reverseOrder()); // newest first per customer

orders.stream().sorted(byCustomerThenDate)
    .collect(Collectors.groupingBy(Order::customerId))
    .forEach((cust, ords) -> {
        System.out.println("Customer: " + cust);
        ords.forEach(o -> System.out.println("  " + o.date() + " $" + o.total()));
    });

Garantie op stabiel sorteren

Java's List.sort() en Arrays.sort() voor objecten gebruiken een stabiele mergesort. Elementen die als gelijk worden vergeleken, behouden hun oorspronkelijke onderlinge volgorde.

// Stable sort example:
// First sort by name, then by dept
// Equal dept elements preserve the name order from previous sort
List<Employee> sorted = employees.stream()
    .sorted(Comparator.comparing(Employee::name))     // 1st pass
    .sorted(Comparator.comparing(Employee::dept))     // 2nd pass (stable!)
    .collect(Collectors.toList());
// Within each dept, employees remain alphabetically sorted

Comparator.comparing met een sleutel-Comparator

Met de vorm met twee argumenten, Comparator.comparing(keyExtractor, keyComparator), kun je zowel de sleutel als de bijbehorende ordening opgeven.

// Sort by name length, then alphabetically within same length
Comparator<String> c = Comparator
    .comparing(String::length, Integer::compare)
    .thenComparing(Comparator.naturalOrder());

List<String> words = new ArrayList<>(List.of("fig","apple","kiwi","banana","pea"));
words.sort(c);
System.out.println(words); // [fig, pea, kiwi, apple, banana]

Praktijkvoorbeeld: zoekresultaten voor vluchten

Zoekresultaten voor vluchten sorteren op prijs, daarna op duur en vervolgens op vertrektijd.

record Flight(String airline, double price, int durationMin, java.time.LocalTime departs) {}

Comparator<Flight> bestFlight = Comparator
    .comparingDouble(Flight::price)
    .thenComparingInt(Flight::durationMin)
    .thenComparing(Flight::departs);

Gesorteerde resultaten verzamelen

Combineer sorteren op meerdere sleutels met collectors om gesorteerde groepen of maps te maken.

Map<String, List<Employee>> byDept = employees.stream()
    .sorted(Comparator.comparing(Employee::dept)
        .thenComparing(Comparator.comparingDouble(Employee::salary).reversed()))
    .collect(Collectors.groupingBy(Employee::dept,
        LinkedHashMap::new,  // preserve insertion (sorted) order
        Collectors.toList()));

byDept.forEach((dept, emps) -> {
    System.out.println(dept + ":");
    emps.forEach(e -> System.out.println("  " + e.name() + " $" + e.salary()));
});

Korte controle

Je wilt werknemers eerst alfabetisch op afdeling sorteren en daarna op aflopend salaris. Welke keten is correct?

Samenvatting: sorteren op meerdere sleutels met thenComparing

Belangrijkste punten:

  • thenComparing() voegt secundaire sorteersleutels toe die worden toegepast wanneer primaire sleutels gelijk zijn
  • Koppel zoveel thenComparing-niveaus aan elkaar als nodig is
  • Gebruik thenComparing(Comparator) met reversed() wanneer de secundaire sleutel in aflopende volgorde moet worden gesorteerd
  • Combineer dit met nullsFirst/nullsLast voor optionele velden
  • List.sort() van Java is stabiel — elementen met gelijke sleutels behouden hun oorspronkelijke volgorde
  • Dynamische sorteerkeuze: gebruik switch om tijdens runtime de juiste Comparator terug te geven
Gratis beginnen

Leer Java met een AI-tutor — gratis

Schrijf echte code en voer die uit in je browser, krijg direct hulp van een AI-tutor die 24/7 beschikbaar is en ga verder waar je gebleven bent op het web of in de app.

Cursussen
104
Lessen
374

Veelgestelde vragen

Is de les “Sorteren op meerdere sleutels met thenComparing” gratis?

Ja — de volledige tekst van “Sorteren op meerdere sleutels met thenComparing” kun je hier gratis op het web lezen. Als je interactief wilt oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is, en de rest van de cursus Java Academy wilt ontgrendelen, kun je upgraden naar CoddyKit PRO. De cursus Java Academy bevat in totaal 4 lessen.

Wat leer ik in “Sorteren op meerdere sleutels met thenComparing”?

Koppel comparators met thenComparing om op meerdere velden te sorteren volgens een prioriteitsvolgorde. Je oefent met Java Academy door code rechtstreeks in de browser uit te voeren. Een AI-begeleider die 24/7 beschikbaar is beantwoordt je vragen terwijl je de les doorwerkt.

Heb ik ervaring nodig om met Java Academy te beginnen?

Ervaring vooraf is niet nodig. Java Academy op CoddyKit is opgebouwd voor beginners tot gevorderden, zodat je hier of bij het begin kunt starten en in je eigen tempo kunt leren. Dit is les 3 van 4.

Hoe lang duurt de les “Sorteren op meerdere sleutels met thenComparing”?

De meeste lessen van CoddyKit duren ongeveer 5–10 minuten. Elke les is kort en interactief, zodat je gestaag vooruitgaat en op het web en in de app precies verdergaat waar je was gebleven.

Kan ik code schrijven en uitvoeren in deze les over Java Academy?

Ja. Elke les over Java Academy bevat een ingebouwde code-editor, zodat je rechtstreeks in je browser echte code kunt schrijven en uitvoeren en direct feedback van AI krijgt — lokale installatie is niet nodig.

Alle lessen in deze cursus

  1. De Comparable-interface
  2. Comparator en sorteren met lambda-expressies
  3. Sorteren op meerdere sleutels met thenComparing
  4. Arrays en collecties sorteren in de praktijk
← Terug naar Java Academy