Algoritmos con Collections
La clase Collections proporciona métodos estáticos de utilidad para operaciones comunes en colecciones.
Ordenamiento
sort()
Ordena una lista usando el orden natural o un Comparator.
List<String> nombres = Arrays.asList("Pedro", "Ana", "Luis", "Carmen");
// Orden natural (alfabético)
Collections.sort(nombres);
// Resultado: [Ana, Carmen, Luis, Pedro]
// Orden inverso
Collections.sort(nombres, Collections.reverseOrder());
// Resultado: [Pedro, Luis, Carmen, Ana]
// Con Comparator personalizado (por longitud)
Collections.sort(nombres, Comparator.comparingInt(String::length));
// Resultado: [Ana, Luis, Pedro, Carmen]
reverse()
Invierte el orden de los elementos.
List<Integer> numeros = Arrays.asList(1, 2, 3, 4, 5);
Collections.reverse(numeros);
// Resultado: [5, 4, 3, 2, 1]
shuffle()
Ordena aleatoriamente los elementos.
List<String> cartas = Arrays.asList("A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K");
// Barajar
Collections.shuffle(cartas);
// Resultado aleatorio: [3, K, 7, A, ...]
// Con semilla para reproducibilidad
Collections.shuffle(cartas, new Random(12345));
rotate()
Rota los elementos de la lista.
List<String> lista = Arrays.asList("A", "B", "C", "D", "E");
// Rotar 2 posiciones a la derecha
Collections.rotate(lista, 2);
// Resultado: [D, E, A, B, C]
// Rotar -1 (1 posición a la izquierda)
Collections.rotate(lista, -1);
// Resultado: [B, C, D, E, A]
swap()
Intercambia dos elementos.
List<String> lista = Arrays.asList("A", "B", "C");
Collections.swap(lista, 0, 2);
// Resultado: [C, B, A]
Búsqueda
binarySearch()
Búsqueda binaria O(log n). Requiere lista ordenada.
List<Integer> numeros = Arrays.asList(1, 3, 5, 7, 9, 11, 13);
Collections.sort(numeros); // Asegurar orden
// Búsqueda exitosa
int index = Collections.binarySearch(numeros, 7);
// Resultado: 3 (índice donde se encuentra)
// Búsqueda fallida
int index = Collections.binarySearch(numeros, 6);
// Resultado: -(punto de inserción) - 1
// Ejemplo: -4 significa que debería ir en índice 3
// Insertar manteniendo orden
int pos = Collections.binarySearch(numeros, 6);
if (pos < 0) {
numeros.add(-pos - 1, 6);
}
max() / min()
Encuentra elementos extremos.
List<Integer> numeros = Arrays.asList(45, 12, 78, 23, 67);
// Orden natural
Integer max = Collections.max(numeros); // 78
Integer min = Collections.min(numeros); // 12
// Con Comparator
String maxLen = Collections.max(nombres, Comparator.comparingInt(String::length));
frequency()
Cuenta ocurrencias de un elemento.
List<String> frutas = Arrays.asList("manzana", "pera", "manzana", "naranja", "manzana");
int count = Collections.frequency(frutas, "manzana");
// Resultado: 3
indexOfSubList() / lastIndexOfSubList()
Busca una sublista dentro de otra.
List<Integer> lista = Arrays.asList(1, 2, 3, 4, 5, 3, 4);
List<Integer> sublista = Arrays.asList(3, 4);
int index = Collections.indexOfSubList(lista, sublista);
// Resultado: 2 (primera ocurrencia)
int lastIndex = Collections.lastIndexOfSubList(lista, sublista);
// Resultado: 5 (última ocurrencia)
Modificación
fill()
Llena la lista con un valor.
List<String> lista = new ArrayList<>(Collections.nCopies(5, ""));
Collections.fill(lista, "X");
// Resultado: [X, X, X, X, X]
copy()
Copia elementos de una lista a otra.
List<String> fuente = Arrays.asList("A", "B", "C");
List<String> destino = new ArrayList<>(Collections.nCopies(3, ""));
Collections.copy(destino, fuente);
// Resultado destino: [A, B, C]
⚠️ La lista destino debe tener al menos el tamaño de la fuente.
replaceAll()
Reemplaza todas las ocurrencias.
List<String> lista = Arrays.asList("a", "b", "a", "c", "a");
Collections.replaceAll(lista, "a", "X");
// Resultado: [X, b, X, c, X]
nCopies()
Crea una lista inmutable con n copias de un elemento.
List<String> lista = Collections.nCopies(5, "X");
// Resultado: [X, X, X, X, X]
// Útil para inicializar listas
List<Integer> ceros = new ArrayList<>(Collections.nCopies(10, 0));
Colecciones Inmutables
Crear colecciones que no pueden modificarse.
// Lista inmutable
List<String> listaInmutable = Collections.unmodifiableList(
Arrays.asList("A", "B", "C")
);
// listaInmutable.add("D"); // Lanza UnsupportedOperationException
// Map inmutable
Map<String, Integer> mapInmutable = Collections.unmodifiableMap(
new HashMap<>()
);
// Set inmutable
Set<String> setInmutable = Collections.unmodifiableSet(
new HashSet<>()
);
Colecciones Singleton
Crear colecciones con un único elemento.
// Lista singleton
List<String> lista = Collections.singletonList("único");
// Set singleton
Set<String> set = Collections.singleton("único");
// Map singleton
Map<String, Integer> map = Collections.singletonMap("clave", 100);
⚠️ Son inmutables.
Colecciones Vacías
Crear colecciones vacías de tipo específico.
List<String> listaVacia = Collections.emptyList();
Set<String> setVacio = Collections.emptySet();
Map<String, Integer> mapVacio = Collections.emptyMap();
// Útil para retornar en lugar de null
public List<String> getElements() {
if (noHayElementos) {
return Collections.emptyList(); // Mejor que null
}
return elementos;
}
Synchronized Collections
Wrappers thread-safe (ver sección de Concurrencia).
List<String> syncList = Collections.synchronizedList(new ArrayList<>());
Map<String, Integer> syncMap = Collections.synchronizedMap(new HashMap<>());
Set<String> syncSet = Collections.synchronizedSet(new HashSet<>());
Implementación en el proyecto
// CollectionsUtilitiesExample.java
public class CollectionsUtilitiesExample {
public static <T extends Comparable<T>> T findMedian(List<T> sortedList) {
if (sortedList.isEmpty()) return null;
int middle = sortedList.size() / 2;
if (sortedList.size() % 2 == 0) {
// Promedio de dos elementos del medio
return sortedList.get(middle - 1);
}
return sortedList.get(middle);
}
public static <T> List<T> getRandomSample(List<T> list, int n) {
List<T> copy = new ArrayList<>(list);
Collections.shuffle(copy);
return copy.subList(0, Math.min(n, copy.size()));
}
}
Escenarios BDD
Escenario: Ordenar lista con Collections.sort
Dado una lista desordenada
Cuando aplico Collections.sort
Entonces la lista queda ordenada
Escenario: Buscar elemento con binarySearch
Dado una lista ordenada
Cuando busco un elemento existente
Entonces obtengo su índice
Escenario: Contar frecuencia
Dado una lista con elementos repetidos
Cuando uso Collections.frequency
Entonces obtengo el conteo correcto
Resumen de métodos
| Categoría | Métodos |
|---|---|
| Ordenamiento | sort, reverse, shuffle, rotate, swap |
| Búsqueda | binarySearch, max, min, frequency |
| Modificación | fill, copy, replaceAll |
| Factory | nCopies, singletonList, singletonMap, emptyList |
| Wrappers | unmodifiableList, synchronizedList |
Conclusión
La clase Collections proporciona herramientas esenciales para manipular colecciones. Conocer estos métodos ahorra código y mejora la legibilidad.