Ordenação por Várias Chaves com thenComparing
Encadeie comparadores com thenComparing para ordenar por vários campos conforme a prioridade.
Ordenação por Várias Chaves com thenComparing é uma aula grátis de Java Academy no CoddyKit. Esta é a aula 3 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Java Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Java Academy inclui 4 aulas no total.
Ordenação por várias chaves
thenComparing() encadeia comparators para ordenar por vários campos. Primeiro ocorre a ordenação principal; em caso de empate, a secundária; e assim por diante.
thenComparing básico
Use thenComparing() para desempatar após o 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);Ordenação em três níveis
Encadeie quantos níveis de thenComparing forem necessários.
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 com Comparator
Use a sobrecarga que aceita um Comparator quando precisar de uma ordenação invertida ou personalizada para as chaves secundárias.
Comparator<Employee> sort = Comparator
.comparing(Employee::dept)
.thenComparing(Comparator.comparing(Employee::salary).reversed()); // highest paid first
// equivalent: .thenComparingDouble(Employee::salary, Comparator.reverseOrder())Ordenando com campos nulos
Combine thenComparing com nullsLast/nullsFirst para lidar adequadamente com campos opcionais.
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);Seleção dinâmica da chave de ordenação
Selecione a chave de ordenação em tempo de execução com base na preferência do usuário.
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 com função extratora
A sobrecarga thenComparing(Function<T,U>) extrai uma chave Comparable para a ordenação secundária sem exigir um 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);Ordenando coleções de registros
Registros com métodos de acesso funcionam perfeitamente com referências de método em cadeias 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()));
});Garantia de ordenação estável
O List.sort() e o Arrays.sort() de Java para objetos usam uma ordenação por intercalação estável. Elementos considerados iguais mantêm sua ordem relativa 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 com Comparator de chave
A forma com dois argumentos Comparator.comparing(keyExtractor, keyComparator) permite especificar tanto a chave quanto sua ordenação.
// 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]Mundo real: resultados da busca de voos
Ordenando os resultados da busca de voos por preço, depois por duração e, por fim, por horário de partida.
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);Coletando resultados ordenados
Combine a ordenação por várias chaves com coletores para produzir grupos ou 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()));
});Verificação rápida
Você quer ordenar os funcionários primeiro por departamento em ordem alfabética e depois por salário em ordem decrescente. Qual cadeia está correta?
Recapitulação: ordenação por várias chaves com thenComparing
Principais conclusões:
- thenComparing() adiciona chaves de ordenação secundárias, aplicadas quando as chaves primárias são iguais
- Encadeie quantos níveis de thenComparing forem necessários
- Use thenComparing com um comparador e reversed() quando a chave secundária precisar de ordem decrescente
- Combine com nullsFirst/nullsLast para campos opcionais
- List.sort() do Java é estável — elementos iguais preservam sua ordem original
- Seleção dinâmica da ordenação: use switch para retornar o comparador correto em tempo de execução
Perguntas Frequentes
A aula “Ordenação por Várias Chaves com thenComparing” é grátis?
Sim — o texto completo de “Ordenação por Várias Chaves com thenComparing” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Java Academy, atualize para CoddyKit PRO. O curso de Java Academy inclui 4 aulas no total.
O que vou aprender em “Ordenação por Várias Chaves com thenComparing”?
Encadeie comparadores com thenComparing para ordenar por vários campos conforme a prioridade. Você pratica Java Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar Java Academy?
Nenhuma experiência prévia é necessária. Java Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 3 de 4.
Quanto tempo leva a aula “Ordenação por Várias Chaves com thenComparing”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de Java Academy?
Sim. Cada aula de Java Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- A Interface Comparable
- Ordenação com Comparator e Lambdas
- Ordenação por Várias Chaves com thenComparing
- Ordenação de Matrizes e Coleções na Prática