Colecciones
¿Qué son las colecciones?
Las colecciones son estructuras de datos que agrupan múltiples elementos. Java proporciona el Java Collections Framework con interfaces y clases listas para usar.
Jerarquía de colecciones
Collection├── List (ordenadas, permiten duplicados)│ ├── ArrayList│ ├── LinkedList│ └── Vector (obsoleta, usar ArrayList)├── Set (no ordenadas, sin duplicados)│ ├── HashSet│ ├── LinkedHashSet (mantiene orden de inserción)│ └── TreeSet (ordenada)└── Queue (colas) ├── LinkedList └── PriorityQueue
Map (no extiende Collection)├── HashMap├── LinkedHashMap└── TreeMapList
ArrayList
Array dinámico. Acceso rápido por índice, inserción lenta en medio.
List<String> nombres = new ArrayList<>();
// Agregar elementosnombres.add("Ana");nombres.add("Luis");nombres.add("María");
// Acceder por índiceString primero = nombres.get(0); // "Ana"
// Modificarnombres.set(1, "Carlos"); // Reemplaza "Luis"
// Eliminarnombres.remove(0); // Elimina "Ana"nombres.remove("María"); // Elimina por valor
// Tamañoint tamaño = nombres.size();
// Verificar si está vacíoif (nombres.isEmpty()) { System.out.println("Lista vacía");}
// Contiene elementoif (nombres.contains("Carlos")) { System.out.println("Carlos está en la lista");}Iterar:
// For-eachfor (String nombre : nombres) { System.out.println(nombre);}
// Con índicefor (int i = 0; i < nombres.size(); i++) { System.out.println(nombres.get(i));}
// IteratorIterator<String> it = nombres.iterator();while (it.hasNext()) { System.out.println(it.next());}
// forEach con lambda (Java 8+)nombres.forEach(nombre -> System.out.println(nombre));nombres.forEach(System.out::println); // Method referenceLinkedList
Lista doblemente enlazada. Inserción/eliminación rápida, acceso lento por índice.
List<String> lista = new LinkedList<>();
lista.add("Primero");lista.add("Segundo");
// También implementa Deque (cola de doble extremo)LinkedList<String> deque = new LinkedList<>();deque.addFirst("Inicio");deque.addLast("Final");String primero = deque.removeFirst();String ultimo = deque.removeLast();¿ArrayList o LinkedList?
- ArrayList: Usa por defecto. Mejor para acceso aleatorio.
- LinkedList: Solo si insertas/eliminas mucho en medio de la lista.
Set
Sin duplicados, no mantiene orden (excepto LinkedHashSet y TreeSet).
HashSet
Set<String> conjunto = new HashSet<>();
conjunto.add("Java");conjunto.add("Python");conjunto.add("Java"); // No se agrega (duplicado)
System.out.println(conjunto.size()); // 2
// Verificar existenciaif (conjunto.contains("Java")) { System.out.println("Contiene Java");}
// Eliminarconjunto.remove("Python");
// Iterarfor (String lenguaje : conjunto) { System.out.println(lenguaje);}LinkedHashSet
Mantiene el orden de inserción:
Set<String> conjunto = new LinkedHashSet<>();conjunto.add("Tercero");conjunto.add("Primero");conjunto.add("Segundo");
// Itera en el orden de inserciónTreeSet
Ordena elementos automáticamente:
Set<Integer> numeros = new TreeSet<>();numeros.add(5);numeros.add(1);numeros.add(3);
System.out.println(numeros); // [1, 3, 5]Map
Asocia claves con valores. Las claves no pueden duplicarse.
HashMap
Map<String, Integer> edades = new HashMap<>();
// Agregar pares clave-valoredades.put("Juan", 25);edades.put("María", 30);edades.put("Carlos", 28);
// Obtener valorint edadJuan = edades.get("Juan"); // 25
// Si no existe, retorna nullInteger edadPedro = edades.get("Pedro"); // null
// getOrDefaultint edad = edades.getOrDefault("Pedro", 0); // 0
// Verificar si existe claveif (edades.containsKey("María")) { System.out.println("María existe");}
// Verificar si existe valorif (edades.containsValue(25)) { System.out.println("Alguien tiene 25 años");}
// Eliminaredades.remove("Carlos");
// Tamañoint tamaño = edades.size();Iterar:
// Por entradas (clave-valor)for (Map.Entry<String, Integer> entry : edades.entrySet()) { System.out.println(entry.getKey() + ": " + entry.getValue());}
// Solo clavesfor (String nombre : edades.keySet()) { System.out.println(nombre);}
// Solo valoresfor (Integer edad : edades.values()) { System.out.println(edad);}
// Con forEach (Java 8+)edades.forEach((nombre, edad) -> System.out.println(nombre + ": " + edad));Métodos útiles (Java 8+):
// putIfAbsent: solo agrega si no existeedades.putIfAbsent("Pedro", 35);
// computeIfAbsent: calcula el valor si no existeMap<String, List<String>> mapa = new HashMap<>();mapa.computeIfAbsent("grupo1", k -> new ArrayList<>()).add("elemento");
// merge: combina valoresedades.merge("Juan", 1, (viejo, nuevo) -> viejo + nuevo); // IncrementaLinkedHashMap
Mantiene orden de inserción:
Map<String, Integer> mapa = new LinkedHashMap<>();TreeMap
Ordena por claves:
Map<String, Integer> mapa = new TreeMap<>();mapa.put("Zebra", 1);mapa.put("Apple", 2);mapa.put("Banana", 3);
// Itera en orden alfabético: Apple, Banana, ZebraQueue
LinkedList como Queue
Queue<String> cola = new LinkedList<>();
// Agregar elementoscola.offer("Primero");cola.offer("Segundo");cola.offer("Tercero");
// Ver el primero sin eliminarloString primero = cola.peek(); // "Primero"
// Eliminar y obtener el primeroString eliminado = cola.poll(); // "Primero"
// Si está vacía, peek() y poll() retornan nullPriorityQueue
Cola con prioridad (min-heap por defecto):
Queue<Integer> pq = new PriorityQueue<>();pq.offer(5);pq.offer(1);pq.offer(3);
System.out.println(pq.poll()); // 1 (el menor)System.out.println(pq.poll()); // 3System.out.println(pq.poll()); // 5Con comparador personalizado:
Queue<String> pq = new PriorityQueue<>( (a, b) -> b.length() - a.length() // Por longitud, descendente);Deque (Double-Ended Queue)
Cola de doble extremo:
Deque<String> deque = new ArrayDeque<>();
// Agregar al inicio y finaldeque.addFirst("Primero");deque.addLast("Último");
// Eliminar del inicio y finalString primero = deque.removeFirst();String ultimo = deque.removeLast();
// Usar como pila (LIFO)deque.push("Elemento");String top = deque.pop();Operaciones útiles
Ordenar listas
List<Integer> numeros = Arrays.asList(5, 2, 8, 1, 9);
// Orden naturalCollections.sort(numeros);
// Con comparadornumeros.sort((a, b) -> b - a); // Descendente
// O con Comparatornumeros.sort(Comparator.reverseOrder());Buscar en listas ordenadas
List<Integer> numeros = Arrays.asList(1, 2, 5, 8, 9);int indice = Collections.binarySearch(numeros, 5); // 2Copiar colecciones
// Copia superficialList<String> copia = new ArrayList<>(original);
// InmutableList<String> inmutable = List.copyOf(original);Convertir array a lista
String[] array = {"uno", "dos", "tres"};
// Lista de tamaño fijo (no se puede agregar/eliminar)List<String> lista1 = Arrays.asList(array);
// Lista mutableList<String> lista2 = new ArrayList<>(Arrays.asList(array));
// Java 9+List<String> lista3 = List.of("uno", "dos", "tres"); // InmutableColecciones inmutables (Java 9+)
List<String> lista = List.of("uno", "dos", "tres");Set<String> conjunto = Set.of("a", "b", "c");Map<String, Integer> mapa = Map.of("uno", 1, "dos", 2);
// No se pueden modificarlista.add("cuatro"); // ❌ UnsupportedOperationExceptionComparar objetos personalizados
Comparable
public class Persona implements Comparable<Persona> { private String nombre; private int edad;
@Override public int compareTo(Persona otra) { return Integer.compare(this.edad, otra.edad); }}
List<Persona> personas = new ArrayList<>();Collections.sort(personas); // Usa compareToComparator
List<Persona> personas = new ArrayList<>();
// Por nombrepersonas.sort(Comparator.comparing(Persona::getNombre));
// Por edadpersonas.sort(Comparator.comparing(Persona::getEdad));
// Por múltiples criteriospersonas.sort( Comparator.comparing(Persona::getEdad) .thenComparing(Persona::getNombre));Buenas prácticas
- Programa contra la interfaz, no la implementación:
// ✅ BuenoList<String> lista = new ArrayList<>();
// ❌ Menos flexibleArrayList<String> lista = new ArrayList<>();- Especifica la capacidad inicial si conoces el tamaño:
List<String> lista = new ArrayList<>(1000); // Evita realocaciones- Usa colecciones inmutables cuando sea posible:
List<String> constantes = List.of("UNO", "DOS", "TRES");- Cuidado con null en colecciones:
// HashSet, HashMap permiten null// TreeSet, TreeMap no permiten nullPróximo paso
Aprende sobre programación funcional y Streams: Streams →