Ordinamento per più chiavi con thenComparing
Concateni i comparatori con thenComparing per ordinare in base a più campi secondo un ordine di priorità.
Ordinamento per più chiavi con thenComparing è una lezione Java Academy gratuita su CoddyKit. Questa è la lezione 3 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Java Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Java Academy include 4 lezioni in totale.
Ordinamento per più chiavi
thenComparing() concatena i comparator per ordinare in base a più campi. Prima viene applicato l'ordinamento principale; in caso di parità, quello secondario, e così via.
thenComparing di base
Utilizzi thenComparing() per risolvere i casi di parità dopo il comparator principale.
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);Ordinamento a tre livelli
Concateni tutti i livelli thenComparing necessari.
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 con Comparator
Utilizzi l'overload che accetta un Comparator quando ha bisogno di un ordinamento invertito o personalizzato per le chiavi secondarie.
Comparator<Employee> sort = Comparator
.comparing(Employee::dept)
.thenComparing(Comparator.comparing(Employee::salary).reversed()); // highest paid first
// equivalent: .thenComparingDouble(Employee::salary, Comparator.reverseOrder())Ordinare con campi null
Combini thenComparing con nullsLast/nullsFirst per gestire con eleganza i campi facoltativi.
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);Selezione dinamica della chiave di ordinamento
Selezioni la chiave di ordinamento in fase di esecuzione in base alla preferenza dell'utente.
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 con una funzione di estrazione
L'overload thenComparing(Function<T,U>) estrae una chiave Comparable per l'ordinamento secondario senza richiedere un Comparator esplicito.
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);Ordinare collezioni di record
I record con metodi accessor funzionano perfettamente con i riferimenti a metodo nelle catene di comparator.
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()));
});Garanzia di ordinamento stabile
List.sort() e Arrays.sort() di Java, quando applicati agli oggetti, utilizzano un merge sort stabile. Gli elementi che risultano uguali secondo il confronto mantengono il loro ordine relativo originale.
// 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 sortedComparator.comparing con un Comparator per la chiave
La forma a due argomenti Comparator.comparing(keyExtractor, keyComparator) consente di specificare sia la chiave sia il relativo ordinamento.
// 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]Caso reale: risultati della ricerca dei voli
Ordinamento dei risultati della ricerca dei voli prima per prezzo, poi per durata e infine per orario di partenza.
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);Raccolta dei risultati ordinati
Combini l'ordinamento con più chiavi con i collector per produrre gruppi o mappe ordinate.
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()));
});Verifica rapida
Desidera ordinare i dipendenti prima alfabeticamente per reparto e poi per stipendio in ordine decrescente. Quale catena è corretta?
Riepilogo: ordinamento con più chiavi con thenComparing
Punti chiave:
- thenComparing() aggiunge chiavi di ordinamento secondarie, applicate quando le chiavi primarie sono uguali
- Può concatenare tutti i livelli thenComparing necessari
- Utilizzi thenComparing(Comparator) con reversed() quando la chiave secondaria deve essere ordinata in modo decrescente
- Combini con nullsFirst/nullsLast per i campi opzionali
- Il metodo List.sort() di Java è stabile: gli elementi uguali mantengono l'ordine originale
- Selezione dinamica dell'ordinamento: utilizzi switch per restituire il Comparator corretto durante l'esecuzione
Domande Frequenti
La lezione «Ordinamento per più chiavi con thenComparing» è gratuita?
Sì — il testo completo di «Ordinamento per più chiavi con thenComparing» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Java Academy, passa a CoddyKit PRO. Il corso Java Academy include 4 lezioni in totale.
Cosa imparerò in «Ordinamento per più chiavi con thenComparing»?
Concateni i comparatori con thenComparing per ordinare in base a più campi secondo un ordine di priorità. Eserciti Java Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare Java Academy?
Non è richiesta alcuna esperienza precedente. Java Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 3 di 4.
Quanto tempo richiede la lezione «Ordinamento per più chiavi con thenComparing»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione Java Academy?
Sì. Ogni lezione Java Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- L'interfaccia Comparable
- Comparator e ordinamento con lambda
- Ordinamento per più chiavi con thenComparing
- Ordinare array e collezioni nella pratica