Colecciones en Java: Pensando como Algoritmista (sin morir en el intento)
Una guía clara y algorítmica sobre las Colecciones en Java. Aprende a leer enunciados, crear pseudocódigo, hacer test de escritorio y resolver usando List, Set y Map.

En los posts anteriores hemos hablado de cómo está diseñado Java por dentro y de la POO con ejemplos bancarios.
Ahora quiero darle un giro a los blogs y meterle más algoritmos, pero sin que se vuelva un libro de universidad aburrido.
La idea es siempre esta:
- Empezar con un enunciado (el problema real).
- Aprender a leerlo como programador.
- Sacar un pseudocódigo clarito.
- Hacer un test de escritorio (simular a mano).
- Recién ahí, escribir el código en Java.
En este post vamos a hacer todo eso usando Colecciones en Java: List, Set y Map.
🧩 Enunciado (el problema)
Estás organizando un taller de Java.
Necesitas guardar la información de las personas que se inscriben:
- Debes registrar el orden de llegada.
- Debes evitar que alguien se registre dos veces con el mismo correo.
- Debes saber cuántas personas vienen por ciudad.
Al final quieres imprimir:
- La lista de inscritos en orden de llegada.
- El total de personas únicas inscritas.
- Un resumen: ciudad → cantidad de asistentes.
Suena sencillo, pero aquí ya tenemos tres necesidades diferentes.
Y cada una grita por una colección distinta 👀
🧠 Cómo leer un enunciado (modo algoritmo ON)
Algo que me enseñaron (y luego no olvidé por años 😂 gracias a DEC Ramiro Giraldo) es esto:
El enunciado te pide lo que necesita y te da lo que requiere.
Nada está ahí porque sí.
Leamos el enunciado con esa idea:
| Frase del enunciado | Qué me está pidiendo | Qué me está dando |
|---|---|---|
| “registrar el orden de llegada” | Una estructura ordenada | La secuencia de inscripciones |
| “evitar que alguien se registre dos veces con el mismo correo” | Necesito unicidad | El correo es el identificador |
| “cuántas personas vienen por ciudad” | Un conteo por grupo (ciudad) | Para cada persona conozco su ciudad |
| “al final quieres imprimir…” | Necesito recorrer y mostrar resultados | Toda la info que guardé durante el proceso |
Si lo traducimos a estructuras de datos:
- Orden de llegada → Lista (
List) - Unicidad por correo → Conjunto (
Set) - Conteo por ciudad → Mapa clave-valor (
Map)
Ya el enunciado nos está apuntando a List, Set y Map sin decirlo explícitamente.
✏️ Pseudocódigo del algoritmo
Antes de tirarnos al código Java, pensemos al paso a paso:
INICIO
crear listaOrdenLlegada // para guardar nombres en orden
crear conjuntoCorreosUnicos // para evitar duplicados
crear mapaCiudadConteo // ciudad -> cantidad de asistentes
MIENTRAS haya más inscripciones
leer nombre, correo, ciudad
SI correo YA está en conjuntoCorreosUnicos
mostrar "Este correo ya está registrado"
continuar con la siguiente inscripción
FIN SI
agregar correo a conjuntoCorreosUnicos
agregar nombre a listaOrdenLlegada
SI ciudad NO existe en mapaCiudadConteo
poner ciudad con valor 1
EN OTRO CASO
aumentar en 1 el contador de esa ciudad
FIN SI
FIN MIENTRAS
// Mostrar resultados
imprimir "Lista en orden de llegada"
recorrer listaOrdenLlegada e imprimir cada nombre
imprimir "Total de personas únicas" = tamaño de conjuntoCorreosUnicos
imprimir "Resumen por ciudad"
recorrer mapaCiudadConteo e imprimir ciudad y cantidad
FIN
🧪 Test de escritorio (simulando a mano)
Supongamos que las inscripciones llegan así:
| # | Nombre | Correo | Ciudad |
|---|---|---|---|
| 1 | Wilmar | wil@dev.com | Medellín |
| 2 | Ana | ana@dev.com | Bogotá |
| 3 | Carlos | carlos@dev.com | Medellín |
| 4 | Wilmar | wil@dev.com | Cali |
| 5 | Luisa | luisa@dev.com | Medellín |
Ahora simulemos cómo van cambiando las estructuras paso a paso:
Estado de las colecciones
| Paso | Acción | listaOrdenLlegada | conjuntoCorreosUnicos | mapaCiudadConteo |
|---|---|---|---|---|
| 1 | Llega Wilmar, wil@dev.com, Medellín | [Wilmar] | {wil@dev.com} | {Medellín → 1} |
| 2 | Llega Ana, ana@dev.com, Bogotá | [Wilmar, Ana] | {wil@dev.com, ana@dev.com} | {Medellín → 1, Bogotá → 1} |
| 3 | Llega Carlos, carlos@dev.com, Medellín | [Wilmar, Ana, Carlos] | {wil@dev.com, ana@dev.com, carlos@dev} | {Medellín → 2, Bogotá → 1} |
| 4 | Llega Wilmar otra vez con wil@dev.com | (no cambia, correo repetido) | (igual) | (igual) |
| 5 | Llega Luisa, luisa@dev.com, Medellín | [Wilmar, Ana, Carlos, Luisa] | {wil, ana, carlos, luisa} | {Medellín → 3, Bogotá → 1} |
Al final:
- Lista en orden: Wilmar, Ana, Carlos, Luisa
- Correos únicos: 4
- Por ciudad: Medellín → 3, Bogotá → 1
Si esto se entiende aquí, el código en Java solo es traducir este comportamiento.
☕ Pasando a Java: colecciones al rescate
Ahora sí, llevemos el pseudocódigo a Java.
1️⃣ Definimos nuestras colecciones
import java.util.*;
public class TallerJava {
public static void main(String[] args) {
// List: mantiene el orden de llegada
List<String> listaOrdenLlegada = new ArrayList<>();
// Set: evita correos repetidos
Set<String> correosUnicos = new HashSet<>();
// Map: ciudad -> cantidad de asistentes
Map<String, Integer> ciudadConteo = new HashMap<>();
// Aquí simulamos las inscripciones
procesarInscripcion("Wilmar", "wil@dev.com", "Medellín",
listaOrdenLlegada, correosUnicos, ciudadConteo);
procesarInscripcion("Ana", "ana@dev.com", "Bogotá",
listaOrdenLlegada, correosUnicos, ciudadConteo);
procesarInscripcion("Carlos", "carlos@dev.com", "Medellín",
listaOrdenLlegada, correosUnicos, ciudadConteo);
procesarInscripcion("Wilmar (duplicado)", "wil@dev.com", "Cali",
listaOrdenLlegada, correosUnicos, ciudadConteo);
procesarInscripcion("Luisa", "luisa@dev.com", "Medellín",
listaOrdenLlegada, correosUnicos, ciudadConteo);
// Al final mostramos el resumen
mostrarResumen(listaOrdenLlegada, correosUnicos, ciudadConteo);
}
}
Todavía falta implementar procesarInscripcion y mostrarResumen, pero ya se ve clarito qué hace cada colección:
List<String> listaOrdenLlegada→ orden de llegadaSet<String> correosUnicos→ que no se repitan correosMap<String, Integer> ciudadConteo→ conteo por ciudad
2️⃣ Implementamos el procesamiento de cada inscripción
static void procesarInscripcion(
String nombre,
String correo,
String ciudad,
List<String> listaOrdenLlegada,
Set<String> correosUnicos,
Map<String, Integer> ciudadConteo
) {
// 1. Validar correo duplicado usando el Set
if (correosUnicos.contains(correo)) {
System.out.println("⚠️ El correo " + correo + " ya está registrado. Ignorando a " + nombre);
return; // salimos y no registramos nada
}
// 2. Registrar correo y nombre
correosUnicos.add(correo); // ahora este correo queda marcado como usado
listaOrdenLlegada.add(nombre); // guardamos el nombre en orden de llegada
// 3. Actualizar conteo por ciudad en el Map
int conteoActual = ciudadConteo.getOrDefault(ciudad, 0);
ciudadConteo.put(ciudad, conteoActual + 1);
System.out.println("✅ Inscrito: " + nombre + " (" + ciudad + ")");
}
Si comparas con el pseudocódigo, es prácticamente lo mismo, solo que con tipos y sintaxis Java.
3️⃣ Mostramos el resumen final
static void mostrarResumen(
List<String> listaOrdenLlegada,
Set<String> correosUnicos,
Map<String, Integer> ciudadConteo
) {
System.out.println("\n📋 Lista en orden de llegada:");
int i = 1;
for (String nombre : listaOrdenLlegada) {
System.out.println(i + ". " + nombre);
i++;
}
System.out.println("\n👥 Total de personas únicas: " + correosUnicos.size());
System.out.println("\n🏙️ Asistentes por ciudad:");
for (Map.Entry<String, Integer> entry : ciudadConteo.entrySet()) {
String ciudad = entry.getKey();
Integer cantidad = entry.getValue();
System.out.println("- " + ciudad + ": " + cantidad);
}
}
Con esto ya resolvimos todo el enunciado original usando colecciones.
🧠 Enfoque algorítmico aplicado a colecciones
Quiero que te quedes con este flujo mental:
-
Lee el enunciado y subraya palabras clave:
- “orden”, “sin repetir”, “por categoría”, “por ciudad”, “por estado”…
-
Traduce esas palabras a estructuras:
- Orden y duplicados permitidos →
List - Sin duplicados →
Set - Agrupar/contar por algo →
Map
- Orden y duplicados permitidos →
-
Haz un test de escritorio:
- Simula 3–5 entradas y mira cómo cambian tus estructuras paso a paso.
-
Recién ahí codifica:
- La idea ya está clara, el código solo la ejecuta.
🧪 Mini-ejercicios para practicar (enunciados)
Te dejo tres enunciados para que practiques el mismo enfoque:
1. Sistema de likes en un artículo
Llevar el registro de:
- Usuarios que han dado like (un usuario no puede dar like dos veces).
- El orden en el que se dieron los likes.
- La cantidad total de likes.
Preguntas para ti:
- ¿Qué estructura usarías para evitar likes repetidos?
- ¿Cuál para el orden de llegada?
- ¿Harías test de escritorio con 4–5 likes?
2. Inventario simple de productos
Tienes ventas de productos con estos datos:
nombreProducto,categoria,cantidadVendida. Quieres saber:
- Lista de productos vendidos en orden de venta.
- Total de productos distintos vendidos.
- Un resumen por categoría:
categoria → total vendidos.
Otra vez, piensa:
- ¿Dónde guardas los productos?
- ¿Dónde controlas los distintos?
- ¿Cómo cuentas por categoría?
3. Registro de errores en un sistema
Cada vez que ocurre un error, llega un código:
ERROR_404,ERROR_500, etc. Quieres:
- Guardar el historial en orden.
- Saber cuántas veces se repitió cada código.
- Tener una lista de códigos únicos.
¿List, Set, Map? Ya sabes por dónde va la cosa 😏
🎯 Cierre
Más que memorizar “List, Set, Map”, lo importante es que empieces a verlos como herramientas para resolver enunciados:
- El enunciado pide cosas → tú decides qué estructuras las soportan mejor.
- El algoritmo se diseña primero en papel / pseudocódigo / test de escritorio.
- Java entra al final, como el lenguaje que implementa esa idea.
Si logras pensar así, las colecciones dejan de ser una lista de clases raras de java.util
y se vuelven tu caja de herramientas diaria 🔧
Espero que ahora de esta forma veas los algoritmos y el codigo Java mas facíl que dormir con la ropa del colegio puesta pa' optimizar 🤠
Comentarios
Inicia sesión para dejar un comentario
Sin comentarios aún. Sé el primero en compartir tu opinión.
Escrito por
Wilmar Garcia Valderrama
Líder Técnico de Desarrollo en QUIND y Fundador de WillDevp. Apasionado por la arquitectura limpia, microservicios y buenas prácticas de ingeniería.
Artículos relacionados

Excepciones en Java: Cuando las cosas salen mal (y cómo no dejar que se cuele algo)
Aprende a manejar excepciones en Java: try-catch, try-with-resources, excepciones personalizadas y mejores prácticas con ejemplos reales.

Cómo está diseñado Java: Objetos, Clases, Herencia, Polimorfismo e Interfaces (Ejemplo Bancario)
Una explicación clara y cercana de cómo está diseñado Java: clases, objetos, herencia, polimorfismo, interfaces y más. Con ejemplos bancarios fáciles de entender y sin enredos.

Primer vistazo a Java: qué tiene y cómo se inicia
Introducción sencilla a Java: ecosistema, JVM, clases, paquetes, módulos y manejo básico de excepciones — te lo explico así como mi abuelita me enseño.