0Pricing
Java Academy · Lección

EnumSet y EnumMap

Use EnumSet y EnumMap para trabajar eficazmente con colecciones basadas en enumeraciones y con seguridad de tipos.

EnumSet y EnumMap es una lección gratuita de Java Academy en CoddyKit. Esta es la lección 4 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Java Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Java Academy incluye 4 lecciones en total.

EnumSet y EnumMap

EnumSet y EnumMap son implementaciones de colecciones altamente optimizadas para enums. Internamente utilizan vectores de bits, por lo que son mucho más rápidas que HashSet/HashMap para claves de enum.

EnumSet: crear conjuntos

EnumSet proporciona métodos de fábrica para crear conjuntos de constantes de enum.

import java.util.*;

enum Day { MON, TUE, WED, THU, FRI, SAT, SUN }

EnumSet<Day> weekdays  = EnumSet.range(Day.MON, Day.FRI);
EnumSet<Day> weekend   = EnumSet.of(Day.SAT, Day.SUN);
EnumSet<Day> allDays   = EnumSet.allOf(Day.class);
EnumSet<Day> noDays    = EnumSet.noneOf(Day.class);

System.out.println(weekdays); // [MON, TUE, WED, THU, FRI]
System.out.println(weekend);  // [SAT, SUN]
System.out.println(allDays.size()); // 7

EnumSet: operaciones de conjuntos

EnumSet admite las operaciones estándar de conjuntos: unión, intersección y complemento. Son extremadamente rápidas gracias a la implementación basada en vectores de bits.

import java.util.*;

enum Permission { READ, WRITE, DELETE, ADMIN, EXPORT }

EnumSet<Permission> userPerms  = EnumSet.of(Permission.READ, Permission.WRITE);
EnumSet<Permission> adminPerms = EnumSet.allOf(Permission.class);

// Complement
EnumSet<Permission> missing = EnumSet.complementOf(userPerms);
System.out.println("Missing: " + missing);
// Missing: [DELETE, ADMIN, EXPORT]

// Intersection (retain)
EnumSet<Permission> shared = EnumSet.copyOf(userPerms);
shared.retainAll(adminPerms);
System.out.println("Shared: " + shared); // [READ, WRITE]

EnumMap: asociar enums con valores

EnumMap utiliza internamente el ordinal del enum como índice de un array, lo que permite una búsqueda O(1) más rápida que con HashMap.

import java.util.*;

enum Quarter { Q1, Q2, Q3, Q4 }

EnumMap<Quarter, Double> revenue = new EnumMap<>(Quarter.class);
revenue.put(Quarter.Q1, 125_000.0);
revenue.put(Quarter.Q2, 148_500.0);
revenue.put(Quarter.Q3, 132_750.0);
revenue.put(Quarter.Q4, 175_200.0);

double total = revenue.values().stream()
    .mapToDouble(Double::doubleValue).sum();
System.out.printf("Annual revenue: $%.0f%n", total);
// Annual revenue: $581450

EnumMap: iterar en orden

EnumMap siempre itera las claves en el orden de declaración del enum, no en el orden de inserción ni en el orden hash.

import java.util.*;

enum Month { JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC }

EnumMap<Month, Integer> salesUnits = new EnumMap<>(Month.class);
salesUnits.put(Month.MAR, 1420);
salesUnits.put(Month.JAN, 980);
salesUnits.put(Month.FEB, 1105);

// Iterates JAN, FEB, MAR (declaration order, not insertion order)
for (var entry : salesUnits.entrySet()) {
    System.out.println(entry.getKey() + ": " + entry.getValue());
}
// JAN: 980
// FEB: 1105
// MAR: 1420

Sistema de permisos con EnumSet

Un sistema de permisos basado en roles que utiliza EnumSet para comprobar permisos de forma eficiente y ofrecer un diseño de API claro.

import java.util.*;

enum Permission { READ, WRITE, DELETE, PUBLISH, ADMIN }

record Role(String name, EnumSet<Permission> permissions) {
    boolean can(Permission p) { return permissions.contains(p); }
}

Role editor = new Role("Editor",
    EnumSet.of(Permission.READ, Permission.WRITE, Permission.PUBLISH));
Role viewer = new Role("Viewer",
    EnumSet.of(Permission.READ));

System.out.println(editor.can(Permission.WRITE));  // true
System.out.println(viewer.can(Permission.DELETE)); // false

Indicadores de funcionalidad con EnumMap

EnumMap es perfecto para sistemas de indicadores de funcionalidad: ofrece búsquedas O(1) rápidas con claves de enum.

import java.util.*;

enum Feature { DARK_MODE, BETA_EDITOR, AI_SUGGESTIONS, EXPORT_PDF }

class FeatureFlags {
    private final EnumMap<Feature, Boolean> flags = new EnumMap<>(Feature.class);

    public FeatureFlags() {
        for (Feature f : Feature.values()) flags.put(f, false);
    }

    public void enable(Feature f)  { flags.put(f, true); }
    public void disable(Feature f) { flags.put(f, false); }
    public boolean isEnabled(Feature f) { return flags.getOrDefault(f, false); }
}

FeatureFlags ff = new FeatureFlags();
ff.enable(Feature.DARK_MODE);
System.out.println(ff.isEnabled(Feature.DARK_MODE));      // true
System.out.println(ff.isEnabled(Feature.AI_SUGGESTIONS)); // false

Rendimiento: EnumSet frente a HashSet

EnumSet utiliza una única máscara de bits long (para enums con 64 constantes o menos); sus operaciones son operaciones de bits O(1). HashSet utiliza buckets hash, que son más lentos y tienen una sobrecarga mayor.

import java.util.*;

enum Day { MON, TUE, WED, THU, FRI, SAT, SUN }

// EnumSet: bit operations on a long value
EnumSet<Day> workDays = EnumSet.range(Day.MON, Day.FRI);

// HashSet: hash table with boxing overhead
Set<Day> hashWorkDays = new HashSet<>(Arrays.asList(
    Day.MON, Day.TUE, Day.WED, Day.THU, Day.FRI));

// Both work, but EnumSet is ~5x faster for contains/add/remove
// and uses less memory
System.out.println(workDays.contains(Day.SAT));     // false
System.out.println(workDays.contains(Day.MON));     // true

EnumMap: getOrDefault y computeIfAbsent

EnumMap admite todas las operaciones de Map, incluidas getOrDefault, computeIfAbsent y merge.

import java.util.*;

enum Category { FOOD, ELECTRONICS, CLOTHING, BOOKS }

EnumMap<Category, List<String>> catalog = new EnumMap<>(Category.class);

// computeIfAbsent creates the list on first use
catalog.computeIfAbsent(Category.BOOKS, k -> new ArrayList<>()).add("Clean Code");
catalog.computeIfAbsent(Category.BOOKS, k -> new ArrayList<>()).add("Effective Java");
catalog.computeIfAbsent(Category.ELECTRONICS, k -> new ArrayList<>()).add("Laptop");

System.out.println(catalog.get(Category.BOOKS));
// [Clean Code, Effective Java]
System.out.println(catalog.getOrDefault(Category.FOOD, List.of()));
// []

Patrón Multimap con EnumMap

Combine EnumMap con valores de tipo List para crear un multimap con claves de enum y agrupar elementos por categoría de forma eficiente.

import java.util.*;
import java.util.stream.*;

enum Priority { LOW, NORMAL, HIGH, URGENT }
record Task(String name, Priority priority) {}

List<Task> tasks = List.of(
    new Task("Fix login bug", Priority.URGENT),
    new Task("Update docs",   Priority.LOW),
    new Task("Add unit tests",Priority.NORMAL),
    new Task("Deploy hotfix", Priority.URGENT)
);

// Group by priority into EnumMap
EnumMap<Priority, List<Task>> byPriority = tasks.stream()
    .collect(Collectors.groupingBy(Task::priority,
        () -> new EnumMap<>(Priority.class),
        Collectors.toList()));

byPriority.forEach((p, ts) ->
    System.out.println(p + ": " + ts.stream().map(Task::name).collect(Collectors.joining(", "))));

Cuándo usar EnumSet frente a EnumMap

Resumen de cuándo elegir cada uno:

  • EnumSet: cuando necesite un conjunto de valores de enum, como permisos, funcionalidades activas o días seleccionados
  • EnumMap: cuando asocie cada constante de enum con un valor, como configuración por funcionalidad, puntuación por nivel o elementos por categoría
  • Ambos: prefiera estas opciones frente a HashSet/HashMap para claves de enum; son más rápidos, utilizan menos memoria y mantienen el orden

Comprobación rápida

¿Qué estructura de datos interna utiliza EnumSet para enums con 64 constantes o menos?

Repaso: EnumSet y EnumMap

Conclusiones principales:

  • EnumSet utiliza un vector de bits, extremadamente rápido para conjuntos de enums pequeños
  • EnumSet.of(), range(), allOf() y noneOf() son métodos de fábrica habituales
  • EnumMap utiliza arrays indexados por ordinal; ofrece búsquedas O(1) y mantiene el orden de declaración
  • Use EnumSet para conjuntos de permisos, indicadores de funcionalidad y filtrado por día de la semana
  • Use EnumMap para configuración por categoría, tablas de puntuaciones y asociaciones de funcionalidad con valores
  • Ambos mantienen el orden de declaración del enum y son más eficientes que las colecciones basadas en hash

Preguntas frecuentes

¿La lección «EnumSet y EnumMap» es gratis?

Sí — el texto completo de «EnumSet y EnumMap» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Java Academy, actualiza a CoddyKit PRO. El curso de Java Academy incluye 4 lecciones en total.

¿Qué aprenderé en «EnumSet y EnumMap»?

Use EnumSet y EnumMap para trabajar eficazmente con colecciones basadas en enumeraciones y con seguridad de tipos. Practicas Java Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar Java Academy?

No se requiere experiencia previa. Java Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 4 de 4.

¿Cuánto tiempo toma la lección «EnumSet y EnumMap»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de Java Academy?

Sí. Cada lección de Java Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. Definición y uso de enumeraciones
  2. Enumeraciones con campos y métodos
  3. Expresiones switch con enumeraciones
  4. EnumSet y EnumMap
← Volver a Java Academy