Laboratorio 08 — Colecciones en Java - jorgealbertopineda78-del/java GitHub Wiki
Unidad: 8 — Colecciones
Duración estimada: 90 minutos
Nivel: Intermedio-Avanzado
En los labs anteriores el sistema RPG almacenaba personajes en arreglos de tamaño fijo:
Personaje[] equipo = new Personaje[3]; // tamaño fijo — inflexible
equipo[0] = new Guerrero(...);Y la bitácora de MotorCombate usaba un ArrayList simple. En un sistema real necesitamos estructuras más poderosas:
- Un roster de personajes que crezca dinámicamente →
ArrayList - Una cola de turnos que respete el orden de llegada →
LinkedList - Un inventario que acceda a items por nombre clave →
HashMap - Un registro de habilidades únicas sin duplicados →
HashSet
- Usar
ArrayList,LinkedList,HashMapyHashSetpara resolver problemas reales - Recorrer colecciones con for-each e iteradores
- Elegir la colección correcta según el caso de uso
- Integrar colecciones al sistema RPG existente
El gremio de aventureros necesita un Sistema de Gestión de Gremio que administre:
- El roster de miembros activos (puede crecer o encogerse)
- La cola de espera para entrar al gremio (orden de llegada)
- El inventario de objetos de cada personaje (nombre → cantidad)
- El catálogo de habilidades únicas registradas en el gremio
┌─────────────────────────────────────────────────────┐
│ GestionGremio │
│ - roster: ArrayList<Personaje> │
│ - colaTurnos: LinkedList<String> │
│ - inventario: HashMap<String, Integer> │
│ - habilidades: HashSet<String> │
│ │
│ + agregarMiembro(Personaje) │
│ + eliminarMiembro(String nombrePersonaje) │
│ + buscarPorNombre(String nombre): Personaje │
│ + mostrarRoster() │
│ │
│ + encolarSolicitante(String nombre) │
│ + atenderSiguiente(): String │
│ + mostrarCola() │
│ │
│ + agregarItem(String item, int cantidad) │
│ + usarItem(String item) │
│ + mostrarInventario() │
│ │
│ + registrarHabilidad(String habilidad) │
│ + tieneHabilidad(String habilidad): boolean │
│ + mostrarHabilidades() │
└─────────────────────────────────────────────────────┘
│ usa
▼
┌───────────────────────┐
│ «abstract» Personaje │ ← clases del Lab06/07
│ Guerrero, Arquero │
│ Druida, Nigromante │
└───────────────────────┘
| Colección | Estructura interna | Acceso | Duplicados | Orden | Úsala cuando... |
|---|---|---|---|---|---|
ArrayList |
Arreglo dinámico | O(1) índice | Sí | Inserción | Necesitas acceso rápido por posición |
LinkedList |
Lista doblemente enlazada | O(n) | Sí | Inserción | Insertas/eliminas mucho al inicio/final |
HashMap |
Tabla hash | O(1) clave | No (claves) | Ninguno | Buscas por clave (nombre → valor) |
HashSet |
Tabla hash | O(1) | No | Ninguno | Necesitas elementos únicos |
Crea GestionGremio.java con la sección de roster:
import java.util.ArrayList;
import java.util.Iterator;
public class GestionGremio {
private ArrayList<Personaje> roster;
private java.util.LinkedList<String> colaTurnos;
private java.util.HashMap<String, Integer> inventario;
private java.util.HashSet<String> habilidades;
public GestionGremio() {
roster = new ArrayList<>();
colaTurnos = new java.util.LinkedList<>();
inventario = new java.util.HashMap<>();
habilidades = new java.util.HashSet<>();
}
// ──────────────────────────────────────────
// SECCIÓN 1 — ArrayList: roster de personajes
// ──────────────────────────────────────────
public void agregarMiembro(Personaje p) {
roster.add(p);
System.out.println("[Gremio] " + p.getNombre() + " se unió al gremio.");
}
public void eliminarMiembro(String nombre) {
Iterator<Personaje> it = roster.iterator();
while (it.hasNext()) {
Personaje p = it.next();
if (p.getNombre().equalsIgnoreCase(nombre)) {
it.remove(); // forma segura de eliminar durante iteración
System.out.println("[Gremio] " + nombre + " abandonó el gremio.");
return;
}
}
System.out.println("[Gremio] No se encontró: " + nombre);
}
public Personaje buscarPorNombre(String nombre) {
for (Personaje p : roster) { // for-each
if (p.getNombre().equalsIgnoreCase(nombre)) {
return p;
}
}
return null;
}
public void mostrarRoster() {
System.out.println("\n=== Roster del Gremio (" + roster.size() + " miembros) ===");
for (int i = 0; i < roster.size(); i++) {
Personaje p = roster.get(i);
System.out.println((i + 1) + ". " + p.getNombre() +
" | Nivel: " + p.getNivel() +
" | Vida: " + p.getPuntosVida());
}
}
}💡 ¿Por qué usar
Iteratoren lugar de for-each para eliminar?
Si eliminas un elemento conroster.remove()dentro de unfor-each, Java lanza
ConcurrentModificationException. ElIteratortiene el métodoit.remove()que
es la forma segura de eliminar durante la iteración.
Agrega estos métodos a GestionGremio:
// ──────────────────────────────────────────
// SECCIÓN 2 — LinkedList: cola de turnos
// ──────────────────────────────────────────
public void encolarSolicitante(String nombre) {
colaTurnos.addLast(nombre); // agrega al final
System.out.println("[Cola] " + nombre +
" en posición " + colaTurnos.size());
}
public String atenderSiguiente() {
if (colaTurnos.isEmpty()) {
System.out.println("[Cola] No hay solicitantes en espera.");
return null;
}
String atendido = colaTurnos.removeFirst(); // saca del frente
System.out.println("[Cola] Atendiendo a: " + atendido);
return atendido;
}
public void mostrarCola() {
System.out.println("\n=== Cola de Espera (" + colaTurnos.size() + ") ===");
int pos = 1;
for (String nombre : colaTurnos) { // for-each sobre LinkedList
System.out.println(pos++ + ". " + nombre);
}
}💡
LinkedListcomo cola (FIFO):
addLast()agrega al final,removeFirst()saca del frente.
Esto implementa el patrón FIFO (First In, First Out) — el primero
en llegar es el primero en ser atendido, igual que una fila real.
3a — HashMap: inventario de objetos
Implementa en GestionGremio los métodos del inventario:
-
agregarItem(String item, int cantidad):- Si la clave ya existe → suma la cantidad al valor actual con
getOrDefault - Si no existe → inserta con
put - Imprime el estado actual del item
- Si la clave ya existe → suma la cantidad al valor actual con
-
usarItem(String item):- Si el item existe y cantidad > 0 → resta 1 con
put - Si la cantidad llega a 0 → elimina la entrada con
remove - Si no existe → imprime mensaje de error
- Si el item existe y cantidad > 0 → resta 1 con
-
mostrarInventario():- Itera con
for (Map.Entry<String, Integer> entry : inventario.entrySet()) - Imprime
entry.getKey()→entry.getValue()
- Itera con
3b — HashSet: habilidades únicas
Implementa en GestionGremio los métodos de habilidades:
-
registrarHabilidad(String habilidad):-
habilidades.add()retornatruesi fue nueva,falsesi ya existía - Imprime el resultado apropiado
-
-
tieneHabilidad(String habilidad): boolean:- Usa
habilidades.contains()
- Usa
-
mostrarHabilidades():- Itera con for-each e imprime cada habilidad
💡
HashSet.add()retorna un booleano:
boolean nueva = habilidades.add("Curación");
Sinuevaesfalse, la habilidad ya estaba registrada.
No hay duplicados en unSet.
Demuestra el sistema con estos 5 bloques:
Bloque 1 — Gestión de roster con ArrayList:
GestionGremio gremio = new GestionGremio();
gremio.agregarMiembro(new Druida("Sylva", 10, 300, 100));
gremio.agregarMiembro(new Nigromante("Malachar", 8, 250, 120));
gremio.agregarMiembro(new Arquero("Legolas", 6, 150, "Arco", 20, 95));
gremio.agregarMiembro(new Guerrero("Thorin", 9, 400, "Hacha", 80));
gremio.mostrarRoster();
gremio.eliminarMiembro("Malachar");
gremio.mostrarRoster();
Personaje encontrado = gremio.buscarPorNombre("Legolas");
if (encontrado != null)
System.out.println("Encontrado: " + encontrado.getNombre());Bloque 2 — Cola de espera con LinkedList:
gremio.encolarSolicitante("Gandalf");
gremio.encolarSolicitante("Aragorn");
gremio.encolarSolicitante("Gimli");
gremio.mostrarCola();
gremio.atenderSiguiente(); // atiende a Gandalf (FIFO)
gremio.mostrarCola();Bloque 3 — Inventario con HashMap:
gremio.agregarItem("Poción de vida", 5);
gremio.agregarItem("Flecha élfica", 30);
gremio.agregarItem("Poción de vida", 3); // suma → 8
gremio.mostrarInventario();
gremio.usarItem("Poción de vida");
gremio.usarItem("Pergamino de fuego"); // no existe
gremio.mostrarInventario();Bloque 4 — Habilidades únicas con HashSet:
gremio.registrarHabilidad("Curación");
gremio.registrarHabilidad("Magia oscura");
gremio.registrarHabilidad("Curación"); // duplicado — no se agrega
gremio.mostrarHabilidades();
System.out.println("¿Tiene flecha? " + gremio.tieneHabilidad("Tiro con arco"));
System.out.println("¿Tiene curación? " + gremio.tieneHabilidad("Curación"));Bloque 5 — Resumen del gremio:
gremio.mostrarRoster();
gremio.mostrarCola();
gremio.mostrarInventario();
gremio.mostrarHabilidades();[Gremio] Sylva se unió al gremio.
[Gremio] Malachar se unió al gremio.
[Gremio] Legolas se unió al gremio.
[Gremio] Thorin se unió al gremio.
=== Roster del Gremio (4 miembros) ===
1. Sylva | Nivel: 10 | Vida: 300
2. Malachar | Nivel: 8 | Vida: 250
3. Legolas | Nivel: 6 | Vida: 150
4. Thorin | Nivel: 9 | Vida: 400
[Gremio] Malachar abandonó el gremio.
=== Roster del Gremio (3 miembros) ===
1. Sylva | Nivel: 10 | Vida: 300
2. Legolas | Nivel: 6 | Vida: 150
3. Thorin | Nivel: 9 | Vida: 400
Encontrado: Legolas
[Cola] Gandalf en posición 1
[Cola] Aragorn en posición 2
[Cola] Gimli en posición 3
=== Cola de Espera (3) ===
1. Gandalf
2. Aragorn
3. Gimli
[Cola] Atendiendo a: Gandalf
=== Cola de Espera (2) ===
1. Aragorn
2. Gimli
[Inventario] Poción de vida: 5
[Inventario] Flecha élfica: 30
[Inventario] Poción de vida: 8 (acumulada)
=== Inventario del Gremio ===
Flecha élfica → 30
Poción de vida → 8
[Inventario] Poción de vida usada. Restante: 7
[Inventario] No existe en inventario: Pergamino de fuego
[Habilidades] Curación registrada.
[Habilidades] Magia oscura registrada.
[Habilidades] Curación ya estaba registrada.
=== Habilidades del Gremio ===
- Curación
- Magia oscura
¿Tiene tiro con arco? false
¿Tiene curación? true
| Criterio | Puntos |
|---|---|
ArrayList: agregar, eliminar con Iterator, buscar, mostrar con for-each e índice |
20 |
LinkedList: encolar, atender (FIFO), mostrar cola con for-each |
20 |
HashMap: agregarItem con getOrDefault, usarItem, mostrar con entrySet |
25 |
HashSet: registrar (detecta duplicados), contiene, mostrar |
20 |
Main demuestra los 5 bloques con salida coherente |
15 |
| Total | 100 |
Responde en respuestas.docx:
- ¿Cuál es la diferencia entre
ArrayListyLinkedList? Describe un escenario concreto del juego donde preferirías cada uno. - ¿Por qué
HashMapno garantiza un orden de inserción al imprimir conentrySet()? ¿Qué colección usarías si el orden importa? - ¿Qué ventaja tiene
HashSetsobreArrayListpara registrar habilidades únicas? ¿Qué pierdes al usarHashSet?
Sube al repositorio en la carpeta lab08_colecciones:
lab08_colecciones/
├── Personaje.java
├── Guerrero.java
├── Arquero.java
├── Druida.java
├── Nigromante.java
├── RpgException.java
├── (demás excepciones del Lab07)
├── GestionGremio.java
└── Main.java
💡 Puedes reutilizar todas las clases de los labs anteriores sin modificarlas.
Laboratorio preparado para el curso de Programación Orientada a Objetos — Ago-Dic 2025