HashSet
HashSet implementa la interfaz Set usando una tabla hash. No permite elementos duplicados y no garantiza orden.
Características principales
| Aspecto | Detalle |
|---|---|
| Estructura | Tabla hash (array de buckets con listas enlazadas) |
| Unicidad | No permite duplicados (basado en hashCode() y equals()) |
| Orden | No garantiza orden de inserción ni orden natural |
| Operaciones | add, remove, contains: O(1) promedio |
| Null | Permite un elemento null |
Cuándo usar HashSet
✅ Ideal para: - Verificar unicidad de elementos - Operaciones de conjunto (unión, intersección, diferencia) - Búsquedas rápidas sin necesidad de orden - Filtrar duplicados de una lista
❌ Evitar cuando: - Necesitas elementos ordenados (usa TreeSet) - Necesitas mantener orden de inserción (usa LinkedHashSet) - Requieres orden predecible al iterar
Ejemplos de uso
Eliminar duplicados
List<String> conDuplicados = Arrays.asList("A", "B", "A", "C", "B");
Set<String> unicos = new HashSet<>(conDuplicados);
// Resultado: ["A", "B", "C"] (orden no garantizado)
Verificar unicidad
Set<String> registrados = new HashSet<>();
public boolean registrarUsuario(String email) {
return registrados.add(email);
// Retorna false si el email ya existe
}
Operaciones de conjunto
Set<Integer> setA = new HashSet<>(Arrays.asList(1, 2, 3, 4));
Set<Integer> setB = new HashSet<>(Arrays.asList(3, 4, 5, 6));
// Unión
Set<Integer> union = new HashSet<>(setA);
union.addAll(setB); // [1, 2, 3, 4, 5, 6]
// Intersección
Set<Integer> interseccion = new HashSet<>(setA);
interseccion.retainAll(setB); // [3, 4]
// Diferencia
Set<Integer> diferencia = new HashSet<>(setA);
diferencia.removeAll(setB); // [1, 2]
Funcionamiento interno
- Calcula
hashCode()del elemento - Determina el bucket usando
hashCode % capacidad - Si hay colisión, usa
equals()para verificar duplicados - Almacena en la lista enlazada del bucket
Implementación en el proyecto
// HashSetExample.java demuestra:
public class HashSetExample {
private final Set<String> elements = new HashSet<>();
public boolean addElement(String element) {
return elements.add(element);
}
public boolean contains(String element) {
return elements.contains(element);
}
}
Escenarios BDD
Escenario: Agregar elemento único
Dado un HashSet vacío
Cuando agrego "Java"
Entonces el tamaño es 1
Y contiene "Java"
Escenario: Intentar agregar duplicado
Dado un HashSet con "Java"
Cuando intento agregar "Java" nuevamente
Entonces el tamaño sigue siendo 1
Y la operación retorna false
Escenario: Eliminar duplicados de lista
Dado una lista con elementos duplicados
Cuando convierto a HashSet
Entonces no hay duplicados
Rendimiento
| Operación | Complejidad | Notas |
|---|---|---|
| add() | O(1) | O(n) si requiere rehashing |
| remove() | O(1) | O(n) en peor caso (colisiones) |
| contains() | O(1) | O(n) en peor caso |
| Iteración | O(n) | n = número de elementos |
Recomendaciones
- hashCode() y equals(): Asegúrate que tus objetos implementen ambos métodos correctamente
- Capacidad inicial: Si conoces el tamaño, usa
new HashSet<>(capacidad) - Load factor: Default 0.75 es óptimo para la mayoría de casos
Conclusión
HashSet es la implementación de Set más rápida para operaciones básicas. Úsala cuando no necesites orden y requieras búsquedas O(1).