Aprende a manejar múltiples datos de forma sencilla
Introducción a Colecciones
Imagina que eres el gerente de una empresa y necesitas guardar información de muchos empleados.
¿Usarías una variable para cada empleado?
String empleado1 = "Juan";
String empleado2 = "María";
String empleado3 = "Carlos";
// ❌ Esto no escala... ¿Y si hay 100 empleados?
🤔 El Problema
Sin colecciones, tu código sería:
❌ Imposible de mantener (1000+ líneas para 1000 datos)
❌ Frágil (un pequeño cambio lo rompe todo)
❌ No escalable (doble trabajo para el doble de datos)
❌ Difícil de entender (caótico)
¡Aquí aparecen las colecciones! Son como contenedores que permiten guardar muchos datos en una sola estructura. Java ofrece varias opciones según lo que necesites:
Tipo
Uso
Ejemplo Mental
Array
Tamaño fijo
Una bandera con 5 posiciones fijas
List
Flexible, ordenado
Una lista editable en tu teléfono
Set
Sin duplicados
Una lista asistencia (cada persona una sola vez)
Map
Clave → Valor
Una agenda de teléfono (nombre → número)
Stream
Procesar datos
Un filtro que procesa datos mientras pasan
✅ La Solución
Con colecciones: Guardar 1000 datos es TAN FÁCIL como guardar 1:
✅ Una sola estructura para todos ellos
✅ Código limpio y mantenible
✅ Fácil de entender
✅ Escalable (más datos = mismo código)
🎯 El Gran Principio
Cada colección existe por una razón. La clave es elegir la correcta para el problema que tienes.
Pregunta clave: Antes de elegir una colección, siempre pregúntate:
¿Conozco el tamaño exacto?
¿Permite duplicados?
¿Es una relación clave-valor?
¿Solo necesito procesar, no guardar?
✨ Ejemplos Prácticos
📌 Array - Horario de atención (fijo)
Caso: Una tienda abre de lunes a viernes. Siempre 5 días (tamaño FIJO).
String[] diasAbiertos = {"Lunes", "Martes", "Miércoles", "Jueves", "Viernes"};
// El tamaño NUNCA cambiará
System.out.println(diasAbiertos[0]); // Lunes
📌 List - Compras en el supermercado (flexible)
Caso: Carrito de compras. Empiezas sin nada, agregas productos, eliminas algunos.
List<String> carrito = new ArrayList<>();
carrito.add("Leche");
carrito.add("Pan");
carrito.add("Huevos");
carrito.remove("Pan"); // Cambié de opinión
// La lista creció y se encogió dinámicamente
📌 Set - Usuarios registrados (sin duplicados)
Caso: Sistema de registro. Un usuario no puede estar dos veces.
Set<String> usuarios = new HashSet<>();
usuarios.add("juan@mail.com");
usuarios.add("ana@mail.com");
usuarios.add("juan@mail.com"); // Rechazado (duplicado)
System.out.println(usuarios.size()); // 2, no 3
📌 Map - Precios de productos (relación clave-valor)
Caso: Tienda. Cada producto tiene un precio único.
Un array es una colección con tamaño FIJO. Una vez creado, no puedes agregar ni quitar elementos.
Analogía 1: Un libreto de teatro con exactamente 5 actos. No puedes agregar un 6to sin reescribir todo.
Analogía 2: Una fila de asientos en un cine. Decides que la fila tendrá 10 asientos y no puedo cambiar eso después.
Analogía 3: Una caja de huevos de 12 espacios. Si quieres 15 huevos, necesitas otra caja, no puedes expandir la actual.
💡 ¿Por qué existen los Arrays?
Los arrays son la forma más básica y rápida de almacenar múltiples datos. Son muy eficientes en memoria y acceso rápido. Pero la desventaja es que NO son flexibles.
Ejemplo: Si eres profesor y sabes que tu clase tiene exactamente 30 estudiantes, un array es perfecto. Pero si es una clase abierta donde vienen y van personas, no lo es.
Características clave:
📏Tamaño fijo - Defines el tamaño al crear y no cambia
📍Índices - Los elementos se identifican por posición (empezando en 0)
⚡Rápido - Acceso directo por índice
Cómo se usa:
// Declarar un array de 3 números
int[] edades = new int[3];
// Asignar valores
edades[0] = 20; // Primera posición
edades[1] = 25; // Segunda posición
edades[2] = 30; // Tercera posición
// O declarar con valores directos
int[] numeros = {10, 20, 30};
// Con for tradicional
for (int i = 0; i < edades.length; i++) {
System.out.println(edades[i]);
}
// Con foreach (más simple)
for (int edad : edades) {
System.out.println(edad);
}
✅ Úsalo cuando:
Sabes exactamente cuántos elementos habrá
El tamaño NO va a cambiar
Estás comenzando a aprender
Ejemplo: 7 días de la semana, 12 meses
❌ NO lo uses cuando:
No sabes cuántos elementos habrá
Necesitas agregar o eliminar elementos
El tamaño cambia constantemente
Ejercicios - Arrays
1️⃣ Crea un array de 5 números y suma todos
int[] nums = {10, 20, 30, 40, 50};
int suma = 0;
for (int n : nums) {
suma += n;
}
System.out.println("Suma: " + suma); // 150
2️⃣ Crea un array de nombres y imprime todos
String[] nombres = {"Ana", "Juan", "Carlos"};
for (String nombre : nombres) {
System.out.println(nombre);
}
3️⃣ Encuentra el número mayor en un array
int[] nums = {5, 12, 8, 3, 15};
int mayor = nums[0];
for (int i = 1; i < nums.length; i++) {
if (nums[i] > mayor) {
mayor = nums[i];
}
}
System.out.println(mayor); // 15
4️⃣ Accede al último elemento sin contar manualmente
int[] datos = {1, 2, 3, 4, 5};
int ultimo = datos[datos.length - 1];
System.out.println(ultimo); // 5
5️⃣ Cuenta cuántos números pares hay
int[] nums = {10, 15, 20, 23, 30};
int pares = 0;
for (int n : nums) {
if (n % 2 == 0) pares++;
}
System.out.println("Pares: " + pares); // 3
int[] nums = {5, 10, 15};
for (int i = 0; i < nums.length; i++) {
nums[i] = nums[i] * 2;
}
for (int n : nums) System.out.print(n + " ");
// Imprime: 10 20 30
🔟 Encuentra el elemento mínimo del array
int[] valores = {25, 12, 8, 30, 15};
int minimo = valores[0];
for (int i = 1; i < valores.length; i++) {
if (valores[i] < minimo) {
minimo = valores[i];
}
}
System.out.println(minimo); // 8
1️⃣1️⃣ Crea una matriz 2D (array de arrays)
int[][] matriz = {{1, 2, 3}, {4, 5, 6}};
for (int[] fila : matriz) {
for (int valor : fila) {
System.out.print(valor + " ");
}
System.out.println();
}
1️⃣2️⃣ Copia los elementos de un array a otro
int[] original = {1, 2, 3, 4, 5};
int[] copia = new int[original.length];
for (int i = 0; i < original.length; i++) {
copia[i] = original[i];
}
// O más fácil: int[] copia = original.clone();
2. List / ArrayList
¿Qué es una List?
Una List es como un Array, pero con tamaño FLEXIBLE. Puedes agregar y eliminar elementos cuando quieras.
Analogía 1: Una lista de tareas en tu teléfono. Puedes agregar tareas, eliminar completadas, sin límites.
Analogía 2: A diferencia de un array que es como una caja de huevos cerrada, una List es como una bolsa elástica que crece cuando agregamos cosas y se encoge cuando sacamos.
Analogía 3: Un carrito de compras. Empiezas sin nada, vas agregando productos según los encuentras, y puedes eliminar cualquiera que cambies de opinión.
💡 Diferencia clave: Array vs List
Array: Tienes que saber cuántos elementos EXACTAMENTE habrá. Es rígido.
List: No sabes cuántos elementos habrá. Empieza vacía y crece según necesites.
Regla de oro: Si el tamaño puede cambiar → USA LIST. Si es fijo → USA ARRAY.
Características clave:
📈Tamaño dinámico - Crece o encoge según necesites
➕Flexible - Agregar y eliminar es fácil (add, remove)
📍Ordenado - Mantiene el orden de inserción
Cómo se usa:
// Crear una List
List<String> nombres = new ArrayList<>();
// Agregar elementos
nombres.add("Ana");
nombres.add("Juan");
nombres.add("Carlos");
// Acceder
System.out.println(nombres.get(0)); // Ana
// Con foreach (recomendado)
for (String nombre : nombres) {
System.out.println(nombre);
}
// Con for tradicional
for (int i = 0; i < nombres.size(); i++) {
System.out.println(nombres.get(i));
}
✅ Úsalo cuando:
No sabes cuántos elementos habrá
Necesitas agregar o eliminar elementos
El tamaño cambia constantemente
Ejemplo: carrito de compras, lista de tareas
Ejercicios - List
1️⃣ Crea una lista de números y suma todos
List<Integer> numeros = new ArrayList<>();
numeros.add(10);
numeros.add(20);
numeros.add(30);
int suma = 0;
for (int num : numeros) suma += num;
System.out.println(suma); // 60
2️⃣ Agrega 5 nombres y muéstralos en orden inverso
List<String> nombres = new ArrayList<>();
nombres.add("Ana"); nombres.add("Juan"); nombres.add("Carlos");
for (int i = nombres.size()-1; i >= 0; i--) {
System.out.println(nombres.get(i));
}
3️⃣ Elimina un elemento específico de la lista
List<String> frutas = new ArrayList<>();
frutas.add("Manzana");
frutas.add("Banana");
frutas.add("Naranja");
frutas.remove("Banana"); // remove por valor
// O: frutas.remove(1); // remove por índice
System.out.println(frutas); // [Manzana, Naranja]
4️⃣ Encuentra el elemento mayor en una List de números
List<Integer> numeros = new ArrayList<>();
numeros.add(5); numeros.add(15); numeros.add(10);
int mayor = numeros.get(0);
for (int num : numeros) {
if (num > mayor) mayor = num;
}
System.out.println(mayor); // 15
5️⃣ Verifica si una List contiene un elemento
List<String> marcas = new ArrayList<>();
marcas.add("Nike");
marcas.add("Adidas");
if (marcas.contains("Nike")) {
System.out.println("¡Encontrada!");
}
List<Integer> todos = new ArrayList<>();
todos.add(5); todos.add(15); todos.add(8); todos.add(20);
List<Integer> mayores = new ArrayList<>();
for (int num : todos) {
if (num > 10) mayores.add(num);
}
System.out.println(mayores); // [15, 20]
9️⃣ Vacía completamente una lista
List<Integer> datos = new ArrayList<>();
datos.add(1); datos.add(2); datos.add(3);
datos.clear();
System.out.println(datos.size()); // 0
🔟 Obtén el índice de un elemento específico
List<String> colores = new ArrayList<>();
colores.add("Rojo");
colores.add("Azul");
colores.add("Verde");
int indice = colores.indexOf("Azul");
System.out.println(indice); // 1
1️⃣1️⃣ Convierte un Array a List
String[] array = {"A", "B", "C"};
List<String> lista = new ArrayList<>(
Arrays.asList(array)
);
System.out.println(lista); // [A, B, C]
1️⃣2️⃣ Copia una lista a otra lista
List<Integer> original = new ArrayList<>();
original.add(1); original.add(2);
List<Integer> copia = new ArrayList<>(original);
copia.add(3); // No afecta original
System.out.println(original); // [1, 2]
System.out.println(copia); // [1, 2, 3]
3. Set (Conjunto)
¿Qué es un Set?
Un Set es una colección que NO permite duplicados. Es como una lista de asistencia: cada persona cuenta solo una vez.
Analogía 1: Un conjunto de amigos únicos. No puedes tener el mismo amigo dos veces en tu lista.
Analogía 2: Una lista de asistencia en clase. "¿Juan está?" "Sí" (se marca). "¿Juan está?" "Ya fue marcado". No puedes marcar dos veces a la misma persona.
Analogía 3: Un set de Pokemon. Cada Pokémon es único. Si intentas agregar uno que ya tienes, el sistema lo rechaza.
💡 ¿Cuándo es útil?
Los Sets son perfectos para:
Validar duplicados: Si hago .add("Juan") dos veces, solo queda UNO
Búsquedas rápidas: Verificar si algo existe es muy rápido
Datos únicos: Correos, IDs, números de documento, etc.
Diferencia: Set te salva de duplicados AUTOMÁTICAMENTE, sin que tengas que validar manualmente.
Características clave:
🚫Sin duplicados - Si intentas agregar uno que ya existe, se ignora
🔀Sin orden garantizado - Los elementos NO están en orden específico
⚡Búsqueda rápida - Verificar si existe algo es muy rápido
Cómo se usa:
// Crear un Set
Set<String> correos = new HashSet<>();
// Agregar elementos
correos.add("a@mail.com");
correos.add("b@mail.com");
correos.add("a@mail.com"); // duplicado, se ignora
// Verificar si existe
if (correos.contains("a@mail.com")) {
System.out.println("Existe!");
}
Set<Integer> a = new HashSet<>(Arrays.asList(1,2,3));
Set<Integer> b = new HashSet<>(Arrays.asList(2,3,4));
a.retainAll(b); // Intersección
System.out.println(a); // [2, 3]
🔟 Compara el tamaño antes y después de agregar duplicados
Map<Integer, String> registro = new HashMap<>();
registro.put(1, "Uno");
registro.put(2, "Dos");
registro.clear();
System.out.println(registro.size()); // 0
1️⃣1️⃣ Obtén un valor con valor por defecto si no existe
Map<String, Integer> edades = new HashMap<>();
edades.put("Ana", 25);
int edad = edades.getOrDefault("Pedro", 0);
System.out.println(edad); // 0
1️⃣2️⃣ Cuenta valores duplicados en un Map
Map<String, String> equipos = new HashMap<>();
equipos.put("Juan", "Rojo");
equipos.put("Ana", "Rojo");
equipos.put("Carlos", "Azul");
int rojos = 0;
for (String color : equipos.values()) {
if (color.equals("Rojo")) rojos++;
}
System.out.println("Rojos: " + rojos); // 2
5. Stream API
¿Qué es un Stream?
Un Stream es una forma elegante de procesar colecciones. NO almacena datos, sino que los filtra, transforma y procesa.
Analogía 1: Un filtro de café: el agua pasa por el filtro transformándose, no se guarda.
Analogía 2: Una línea de producción en fábrica. El producto entra, se transforma en estaciones, sale un producto diferente. Pero el proceso es lo importante, no el almacenamiento.
Analogía 3: Un inspector de correo. Lee cartas (filter), puede marcar algunas (map), luego las envía. El inspector no GUARDA las cartas.
💡 Stream NO es una colección
IMPORTANTE: Un Stream NO almacena datos. Es solo un "pipeline" de procesamiento.
Comparación:
List: GUARDA "Juan", "Ana", "Carlos" en memoria
Stream: PROCESA "Juan", "Ana", "Carlos". No los guarda (a menos que captures el resultado)
Por eso es más eficiente: no creas una colección nueva, solo "filtras" la que ya existe.