Ordenar arrays en Java
Ordena arrays de primitivos y objetos en Java con Arrays.sort y comparadores personalizados para objetos.
Ordenar es una de esas operaciones que utilizarás constantemente, y la biblioteca estándar de Java lo convierte en una sola línea — la mayor parte del tiempo. El detalle es que el tipo de elemento importa: los primitivos se ordenan de una manera, los objetos de otra, y "quiero orden descendente" o "ordenar por un campo" requiere un Comparator. Este capítulo recorre todo eso.
El método principal es Arrays.sort. Ordena en su lugar — muta el array que le pasas. Si quieres conservar el original, cópialo primero.
Ordenar primitivos
Para int[], long[], double[], char[], etc., basta con una llamada:
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]El orden de los primitivos es siempre ascendente. No existe una sobrecarga con Comparator — los primitivos no se pueden comparar mediante una función arbitraria como sí pueden hacerlo los objetos.
Para ordenar de manera descendente, el truco consiste en convertirlos a Integer[] y suministrar un comparador, o bien ordenar ascendentemente e invertir 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;
}Ordenar un rango
Pasa from (inclusive) y to (exclusivo) para ordenar solo una parte del 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 sortedLos elementos fuera del rango permanecen en su lugar.
Ordenar arrays de objetos (orden natural)
Para un array de objetos cuya clase implementa Comparable<T> — String, los envoltorios numéricos, LocalDate, cualquier cosa con un orden "natural" — llama directamente a Arrays.sort:
String[] words = {"banana", "apple", "cherry"};
Arrays.sort(words);
// {"apple", "banana", "cherry"} — alphabeticalSi la clase no implementa Comparable, esto lanza una ClassCastException en tiempo de ejecución. La solución es suministrar un Comparator.
Ordenar con un Comparator
Un Comparator<T> es una función que, dados dos valores de tipo T, devuelve un número negativo, cero o un número positivo para indicar "el primero es menor", "son iguales", "el primero es mayor". La forma más limpia de construir uno es con 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));La cadena Comparator.comparing(...).reversed() y .thenComparing(...) es la forma idiomática de componer órdenes de clasificación. Casi nunca necesitas escribir una clase comparadora a mano. Para una mirada más detallada sobre la diferencia entre el orden natural de una clase y un Comparator externo, consulta Comparable vs Comparator.
Manejo de elementos null
Un comparador ordinario lanza una NullPointerException si el array contiene un null. Envuélvelo con Comparator.nullsFirst o Comparator.nullsLast para desplazar los nulls a un extremo:
String[] words = {"banana", null, "apple"};
Arrays.sort(words, Comparator.nullsFirst(Comparator.naturalOrder()));
// {null, "apple", "banana"}Ordenar primitivos encuadrados
Integer[], Double[], etc. son arrays de objetos — por lo tanto, toda la maquinaria de Comparator está disponible:
Integer[] nums = {3, 1, 4, 1, 5};
Arrays.sort(nums, Comparator.reverseOrder());
// {5, 4, 3, 1, 1}Si necesitas orden descendente para un array de primitivos, el encuadre es la ruta más limpia — siempre que el array no sea enorme, el coste es aceptable.
Estabilidad
La estabilidad de la ordenación significa que los elementos iguales mantienen su orden relativo original. La ordenación de objetos en Java es estable: si dos Player tienen la misma puntuación, el que llegó primero se mantiene primero. La ordenación de primitivos no garantiza estabilidad, pero como los primitivos no tienen identidad más allá de su valor, no se puede apreciar.
Esto importa cuando encadenas ordenaciones — p. ej., ordenar por puntuación y luego por nombre. Con una ordenación estable, el segundo paso preserva el orden del primero donde la nueva clave empata. Con thenComparing, compones ambas claves en un solo comparador y evitas el problema, lo que suele ser el enfoque más limpio.
parallelSort
Para arrays muy grandes, Arrays.parallelSort distribuye el trabajo entre múltiples hilos:
int[] huge = new int[10_000_000];
// ... fill huge ...
Arrays.parallelSort(huge);Misma API, misma semántica en su lugar. Hay sobrecarga al configurar los hilos, por lo que para arrays pequeños un sort simple es más rápido. El punto de cruce está alrededor de decenas de miles de elementos; por debajo de eso, no vale la pena.
Si tus datos viven en una List en lugar de un array, el equivalente es Collections.sort o list.sort(...) — se aplican las mismas reglas de comparador. Consulta cómo ordenar un ArrayList.
Un ejemplo práctico
Qué viene después
Ya has visto el lado de lectura y transformación de los arrays. El último capítulo de esta parte cubre copiar arrays — la forma correcta de duplicar, recortar y redimensionar un array existente sin entrelazar los dos con referencias compartidas.