Collections Framework
List, Set y Map — interfaces, implementaciones y criterios de elección
List: secuencia ordenada
List es la colección más usada. Mantiene el orden de inserción y permite duplicados. ArrayList (basada en array interno) es la implementación predeterminada — acceso por índice en O(1). LinkedList es mejor cuando se insertan o eliminan elementos frecuentemente en el medio de la lista.
import java.util.*;
// List: secuencia ordenada con duplicados permitidos
List<String> nombres = new ArrayList<>(); // implementación más usada: array redimensionable
nombres.add("Ana");
nombres.add("Luis");
nombres.add("Ana"); // duplicados permitidos
nombres.add(1, "Eva"); // insertar en posición
String primero = nombres.get(0); // "Ana"
nombres.set(0, "Carlos"); // reemplazar
nombres.remove("Luis"); // por valor
nombres.remove(0); // por índice
int pos = nombres.indexOf("Ana"); // -1 si no existe
boolean existe = nombres.contains("Eva");
// LinkedList: mejor rendimiento al insertar/eliminar en el medio
List<String> lista = new LinkedList<>();
// ArrayList mejor para acceso por índice; LinkedList para inserciones frecuentes en medio Set: sin duplicados
Set garantiza que no haya duplicados. La decisión de si dos objetos son iguales depende de equals() y hashCode() — si no los sobreescribes en tu clase, dos instancias distintas nunca se considerarán
duplicadas.
// Set: sin duplicados, sin orden garantizado (salvo implementaciones concretas)
// HashSet: O(1) para add/contains/remove — sin orden
Set<String> ciudades = new HashSet<>();
ciudades.add("Madrid");
ciudades.add("Barcelona");
ciudades.add("Madrid"); // ignorado: ya existe
// ciudades.size() == 2
// LinkedHashSet: mantiene el orden de inserción
Set<String> ordenadas = new LinkedHashSet<>();
ordenadas.add("Z"); ordenadas.add("A"); ordenadas.add("M");
// iteración: Z, A, M
// TreeSet: orden natural (Comparable) o Comparator personalizado
Set<String> alfabetico = new TreeSet<>();
alfabetico.add("Z"); alfabetico.add("A"); alfabetico.add("M");
// iteración: A, M, Z — O(log n) para operaciones Map: pares clave-valor
Map almacena pares clave-valor con claves únicas. HashMap
es la implementación habitual — acceso en O(1). Las claves deben implementar correctamente
equals() y hashCode().
// Map: pares clave-valor, claves únicas
Map<String, Integer> edades = new HashMap<>();
edades.put("Ana", 30);
edades.put("Luis", 25);
edades.put("Ana", 31); // reemplaza el valor anterior
Integer edad = edades.get("Ana"); // 31
Integer noExiste = edades.get("Pedro"); // null si no existe
int conDefault = edades.getOrDefault("Pedro", 0); // 0 si no existe
edades.containsKey("Luis"); // true
edades.containsValue(25); // true
edades.remove("Luis");
// Iterar sobre el mapa
for (Map.Entry<String, Integer> entrada : edades.entrySet()) {
System.out.println(entrada.getKey() + " → " + entrada.getValue());
}
// LinkedHashMap: mantiene orden de inserción
// TreeMap: orden natural de claves Criterios de elección
// Criterios de elección:
//
// ¿Necesitas índices?
// → List (ArrayList para acceso, LinkedList para inserciones frecuentes en el medio)
//
// ¿Solo necesitas saber si algo existe (sin duplicados)?
// → Set (HashSet más rápido, TreeSet si necesitas orden, LinkedHashSet para orden de inserción)
//
// ¿Necesitas asociar claves con valores?
// → Map (HashMap más rápido, TreeMap si necesitas orden por clave)
//
// Capacidades de rendimiento:
// HashMap / HashSet: O(1) amortizado para get/put/contains
// TreeMap / TreeSet: O(log n) para get/put/contains, pero ordenado
// ArrayList: O(1) para get(idx), O(n) para insertar en el medio
// LinkedList: O(n) para get(idx), O(1) para insertar si tienes el iterador
// Inicialización conveniente (Java 8 — inmutables en Java 9+):
List<String> inmutable = Collections.unmodifiableList(Arrays.asList("a", "b", "c"));
Map<String, Integer> mapa = new HashMap<String, Integer>() {{
put("a", 1); put("b", 2);
}}; // doble-brace initialization: funciona pero crea una subclase anónima — evitar