Ordenación por varias claves con thenComparing
Encadene comparadores con thenComparing para ordenar por varios campos según su prioridad.
Ordenación por varias claves con thenComparing es una lección gratuita de Java Academy en CoddyKit. Esta es la lección 3 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Java Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Java Academy incluye 4 lecciones en total.
Ordenación por varias claves
thenComparing() encadena Comparators para ordenar por varios campos. Primero se aplica la ordenación principal; si hay empate, la secundaria, y así sucesivamente.
thenComparing básico
Use thenComparing() para resolver los empates después del Comparator principal.
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);Ordenación en tres niveles
Encadene tantos niveles de thenComparing como necesite.
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
Use la sobrecarga que acepta un Comparator cuando necesite un orden invertido o personalizado para las claves secundarias.
Comparator<Employee> sort = Comparator
.comparing(Employee::dept)
.thenComparing(Comparator.comparing(Employee::salary).reversed()); // highest paid first
// equivalent: .thenComparingDouble(Employee::salary, Comparator.reverseOrder())Ordenar con campos null
Combine thenComparing con nullsLast/nullsFirst para gestionar correctamente los campos opcionales.
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);Selección dinámica de la clave de ordenación
Seleccione la clave de ordenación en tiempo de ejecución según las preferencias del usuario.
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 función extractora
La sobrecarga thenComparing(Function<T,U>) extrae una clave Comparable para la ordenación secundaria sin necesitar un Comparator explícito.
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);Ordenar colecciones de records
Los records con métodos accessor funcionan perfectamente con referencias a métodos en cadenas de Comparators.
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()));
});Garantía de ordenación estable
La operación List.sort() de Java y Arrays.sort() para objetos utilizan una ordenación por mezcla estable. Los elementos que se comparan como iguales conservan su orden relativo original.
// 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 de claves
La forma de dos argumentos Comparator.comparing(keyExtractor, keyComparator) permite especificar tanto la clave como su ordenación.
// 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 real: resultados de búsqueda de vuelos
Ordenar los resultados de búsqueda de vuelos por precio, después por duración y, por último, por hora de salida.
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);Recopilación de resultados ordenados
Combine la ordenación por varias claves con collectors para generar grupos o mapas ordenados.
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()));
});Comprobación rápida
Desea ordenar empleados primero por departamento alfabéticamente y después por salario en orden descendente. ¿Qué cadena es correcta?
Recapitulación: ordenación por varias claves con thenComparing
Aspectos clave:
- thenComparing() añade criterios de ordenación secundarios que se aplican cuando los criterios principales son iguales
- Encadene tantos niveles de thenComparing como necesite
- Utilice thenComparing(Comparator) con reversed() cuando la clave secundaria necesite un orden descendente
- Combínelos con nullsFirst/nullsLast para campos opcionales
- List.sort() de Java es estable: los elementos iguales conservan su orden original
- Selección dinámica de la ordenación: utilice switch para devolver el Comparator adecuado en tiempo de ejecución
Preguntas frecuentes
¿La lección «Ordenación por varias claves con thenComparing» es gratis?
Sí — el texto completo de «Ordenación por varias claves con thenComparing» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Java Academy, actualiza a CoddyKit PRO. El curso de Java Academy incluye 4 lecciones en total.
¿Qué aprenderé en «Ordenación por varias claves con thenComparing»?
Encadene comparadores con thenComparing para ordenar por varios campos según su prioridad. Practicas Java Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar Java Academy?
No se requiere experiencia previa. Java Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 3 de 4.
¿Cuánto tiempo toma la lección «Ordenación por varias claves con thenComparing»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de Java Academy?
Sí. Cada lección de Java Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- La interfaz Comparable
- Comparator y ordenación con lambdas
- Ordenación por varias claves con thenComparing
- Ordenación de arrays y colecciones en la práctica