Ordenando Arrays em Java
Ordene arrays Java de primitivos e objetos com Arrays.sort e comparadores personalizados para objetos.
Ordenação é uma das operações que você vai usar constantemente, e a biblioteca padrão do Java transforma isso em uma linha — na maioria das vezes. O detalhe é que o tipo do elemento importa: primitivos ordenam de uma forma, objetos de outra, e "quero ordem decrescente" ou "ordenar por um campo" requer um Comparator. Este capítulo cobre tudo isso.
O método principal é Arrays.sort. Ele ordena no lugar — ele muta o array que você passa. Se quiser manter o original, copie-o primeiro.
Ordenando primitivos
Para int[], long[], double[], char[], etc., uma chamada é suficiente:
import java.util.Arrays;
int[] data = {3, 1, 4, 1, 5, 9, 2, 6};
Arrays.sort(data);
System.out.println(Arrays.toString(data)); // [1, 1, 2, 3, 4, 5, 6, 9]A ordenação de primitivos é sempre crescente. Não há sobrecarga com Comparator — primitivos não podem ser comparados por uma função arbitrária como os objetos.
Para ordenar em ordem decrescente, o truque é converter para Integer[] e fornecer um comparador, ou ordenar de forma crescente e inverter manualmente:
int[] data = {3, 1, 4};
Arrays.sort(data);
// reverse in place
for (int i = 0, j = data.length - 1; i < j; i++, j--) {
int tmp = data[i]; data[i] = data[j]; data[j] = tmp;
}Ordenando um intervalo
Passe from (inclusivo) e to (exclusivo) para ordenar apenas parte do array:
int[] data = {9, 8, 7, 6, 5, 4, 3, 2, 1};
Arrays.sort(data, 2, 6);
// {9, 8, 4, 5, 6, 7, 3, 2, 1} — only positions 2..5 sortedOs elementos fora do intervalo permanecem no lugar.
Ordenando arrays de objetos (ordem natural)
Para um array de objetos cuja classe implementa Comparable<T> — String, os wrappers numéricos encapsulados, LocalDate, qualquer coisa com uma ordem "natural" — chame Arrays.sort diretamente:
String[] words = {"banana", "apple", "cherry"};
Arrays.sort(words);
// {"apple", "banana", "cherry"} — alphabeticalSe a classe não implementar Comparable, isso lança ClassCastException em tempo de execução. A solução é fornecer um Comparator.
Ordenando com um Comparator
Um Comparator<T> é uma função que, dados dois Ts, retorna um número negativo, zero ou um número positivo para indicar "o primeiro é menor", "iguais", "o primeiro é maior". A forma mais limpa de criar um é com Comparator.comparing:
record Player(String name, int score) {}
Player[] players = {
new Player("Ada", 1500),
new Player("Linus", 1800),
new Player("Grace", 1650)
};
// sort by score, ascending
Arrays.sort(players, Comparator.comparing(Player::score));
// sort by score, descending
Arrays.sort(players, Comparator.comparing(Player::score).reversed());
// sort by name (case-insensitive), then by score as tiebreaker
Arrays.sort(players,
Comparator.comparing(Player::name, String.CASE_INSENSITIVE_ORDER)
.thenComparing(Player::score));A cadeia Comparator.comparing(...).reversed() e .thenComparing(...) é a forma idiomática de compor ordens de classificação. Você quase nunca precisa escrever uma classe comparadora manualmente. Para uma análise mais aprofundada da diferença entre a ordem natural de uma classe e um Comparator externo, veja Comparable vs Comparator.
Tratando elementos null
Um comparador simples lança NullPointerException se o array contiver um null. Envolva-o com Comparator.nullsFirst ou Comparator.nullsLast para mover os nulls para uma extremidade:
String[] words = {"banana", null, "apple"};
Arrays.sort(words, Comparator.nullsFirst(Comparator.naturalOrder()));
// {null, "apple", "banana"}Ordenando primitivos encapsulados
Integer[], Double[], etc. são arrays de objetos — portanto, toda a maquinaria do Comparator está disponível:
Integer[] nums = {3, 1, 4, 1, 5};
Arrays.sort(nums, Comparator.reverseOrder());
// {5, 4, 3, 1, 1}Se você precisar de ordem decrescente para um array de primitivos, o encapsulamento é a abordagem mais limpa — assumindo que o array não seja enorme, o custo é aceitável.
Estabilidade
A estabilidade de ordenação significa que elementos iguais mantêm sua ordem relativa original. A ordenação de objetos em Java é estável: se dois Players têm a mesma pontuação, o que veio primeiro permanece primeiro. A ordenação de primitivos não tem estabilidade garantida, mas como primitivos não carregam identidade além de seu valor, você não consegue perceber.
Isso importa quando você encadeia ordenações — por exemplo, ordenar por pontuação e depois por nome. Com uma ordenação estável, a segunda passagem preserva a primeira ordenação onde a nova chave empata. Com thenComparing, você compõe ambas as chaves em um único comparador e evita a questão, o que geralmente é a abordagem mais limpa.
parallelSort
Para arrays muito grandes, Arrays.parallelSort distribui o trabalho entre múltiplas threads:
int[] huge = new int[10_000_000];
// ... fill huge ...
Arrays.parallelSort(huge);Mesma API, mesma semântica de operação no lugar. Há overhead na configuração das threads, portanto para arrays pequenos um sort simples é mais rápido. O ponto de cruzamento fica em torno de dezenas de milhares de elementos; abaixo disso, não vale a pena.
Se seus dados estiverem em uma List em vez de um array, o equivalente é Collections.sort ou list.sort(...) — as mesmas regras de comparador se aplicam. Veja como ordenar um ArrayList.
Um exemplo prático
O que vem a seguir
Você viu agora o lado de leitura e transformação dos arrays. O último capítulo desta parte cobre como copiar arrays — a maneira correta de duplicar, fatiar e redimensionar um array existente sem entrelaçá-los com referências compartilhadas.