Skip to content
Java collections 6 min read

EnumSet & EnumMap

When your keys or elements are enum constants, EnumSet and EnumMap are the fastest collections in Java’s toolbox. Both live in java.util, work exclusively with enums, and are backed by extremely compact internal structures — making them quicker and more memory-efficient than their general-purpose siblings like HashSet or HashMap.

Why EnumSet and EnumMap Exist

General-purpose collections (HashSet, HashMap) use hashing and object references — flexible, but heavyweight for enums. Because enum constants have a known count and a fixed ordinal (0, 1, 2, …), Java can replace hash buckets with a plain bit vector or a tightly-packed array, giving you O(1) everything with almost zero overhead.


EnumSet

EnumSet<E extends Enum<E>> is a Set implementation designed exclusively for enum values. Every operation — add, remove, contains, iteration — runs in constant time and uses a single long (or an array of longs for large enums) as its backing store.

Creating an EnumSet

import java.util.EnumSet;

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

public class EnumSetDemo {
    public static void main(String[] args) {

        // All constants
        EnumSet<Day> week = EnumSet.allOf(Day.class);
        System.out.println("Full week: " + week);

        // A hand-picked subset
        EnumSet<Day> workdays = EnumSet.of(Day.MON, Day.TUE, Day.WED, Day.THU, Day.FRI);
        System.out.println("Workdays: " + workdays);

        // A contiguous range (ordinal order)
        EnumSet<Day> weekend = EnumSet.range(Day.SAT, Day.SUN);
        System.out.println("Weekend: " + weekend);

        // Complement — everything NOT in workdays
        EnumSet<Day> offDays = EnumSet.complementOf(workdays);
        System.out.println("Off days: " + offDays);

        // Start empty, then add
        EnumSet<Day> empty = EnumSet.noneOf(Day.class);
        empty.add(Day.FRI);
        System.out.println("TGIF set: " + empty);
    }
}

Output:

Full week: [MON, TUE, WED, THU, FRI, SAT, SUN]
Workdays: [MON, TUE, WED, THU, FRI]
Weekend: [SAT, SUN]
Off days: [SAT, SUN]
TGIF set: [FRI]

Factory Methods at a Glance

MethodWhat it creates
EnumSet.allOf(E.class)All constants of the enum
EnumSet.noneOf(E.class)An empty set (same element type)
EnumSet.of(E e, E... rest)A set with the listed constants
EnumSet.range(E from, E to)Constants from from to to (inclusive, ordinal order)
EnumSet.complementOf(EnumSet<E>)All constants not in the given set
EnumSet.copyOf(Collection<E>)A set initialized from any collection of enums

Note: EnumSet is not thread-safe. Wrap it with Collections.synchronizedSet() if multiple threads share it.

EnumSet as a Set

EnumSet fully implements java.util.Set, so all the familiar operations work:

import java.util.EnumSet;

enum Permission { READ, WRITE, EXECUTE, DELETE }

public class PermissionCheck {
    public static void main(String[] args) {
        EnumSet<Permission> userPerms = EnumSet.of(Permission.READ, Permission.WRITE);

        System.out.println("Can read?    " + userPerms.contains(Permission.READ));
        System.out.println("Can delete?  " + userPerms.contains(Permission.DELETE));

        userPerms.add(Permission.EXECUTE);
        userPerms.remove(Permission.WRITE);
        System.out.println("Updated: " + userPerms);
    }
}

Output:

Can read?    true
Can delete?  false
Updated: [READ, EXECUTE]

Iterating an EnumSet

Iteration follows the natural ordinal order of the enum — always predictable, never random:

for (Day d : EnumSet.range(Day.MON, Day.FRI)) {
    System.out.println("Workday: " + d);
}

Tip: Because the iteration order matches your enum declaration order, EnumSet is a cleaner alternative to a sorted HashSet whenever your elements are enums.


EnumMap

EnumMap<K extends Enum<K>, V> is a Map implementation where the keys must be enum constants. Internally it uses a plain Object[] array indexed by each constant’s ordinal, making every get and put a single array lookup — as fast as it gets.

Creating and Using an EnumMap

import java.util.EnumMap;
import java.util.Map;

enum Planet { MERCURY, VENUS, EARTH, MARS }

public class EnumMapDemo {
    public static void main(String[] args) {
        EnumMap<Planet, Double> gravity = new EnumMap<>(Planet.class);

        gravity.put(Planet.MERCURY, 3.7);
        gravity.put(Planet.VENUS,   8.87);
        gravity.put(Planet.EARTH,   9.81);
        gravity.put(Planet.MARS,    3.72);

        for (Map.Entry<Planet, Double> entry : gravity.entrySet()) {
            System.out.printf("%-10s → %.2f m/s²%n",
                              entry.getKey(), entry.getValue());
        }
    }
}

Output:

MERCURY    → 3.70 m/s²
VENUS      → 8.87 m/s²
EARTH      → 9.81 m/s²
MARS       → 3.72 m/s²

Like EnumSet, iteration order matches the enum’s declaration order — no sorting needed.

Practical Pattern: Counting with EnumMap

A common real-world use case is grouping or counting things by category:

import java.util.EnumMap;

enum Priority { LOW, MEDIUM, HIGH, CRITICAL }

public class TaskCounter {
    public static void main(String[] args) {
        EnumMap<Priority, Integer> counts = new EnumMap<>(Priority.class);

        // Initialize all buckets to zero
        for (Priority p : Priority.values()) {
            counts.put(p, 0);
        }

        // Simulate incoming tasks
        Priority[] incoming = {Priority.HIGH, Priority.LOW, Priority.HIGH,
                               Priority.CRITICAL, Priority.MEDIUM, Priority.HIGH};

        for (Priority p : incoming) {
            counts.merge(p, 1, Integer::sum);
        }

        counts.forEach((p, n) -> System.out.println(p + ": " + n + " task(s)"));
    }
}

Output:

LOW: 1 task(s)
MEDIUM: 1 task(s)
HIGH: 3 task(s)
CRITICAL: 1 task(s)

Note: EnumMap allows null values but not null keys. Attempting to use a null key throws a NullPointerException.


Under the Hood

EnumSet — bit manipulation

EnumSet is abstract. The JDK provides two concrete subclasses you never reference directly:

  • RegularEnumSet — used when the enum has 64 or fewer constants. The entire set fits in a single long field. Adding constant X sets bit X.ordinal() in that long; contains is a single bitwise AND; iteration scans set bits with Long.numberOfTrailingZeros. This is about as fast as a CPU can go.
  • JumboEnumSet — used for enums with more than 64 constants. The bits are spread across a long[] array.

The factory method EnumSet.of(...) automatically picks the right subclass, so you never need to think about it.

EnumMap — array lookup

EnumMap stores values in an Object[] vals array. Each put(key, value) call does vals[key.ordinal()] = value. Each get(key) call returns vals[key.ordinal()]. No hashing, no probing, no linked-list traversal — just a direct array index. This is why EnumMap benchmarks show it to be roughly 2–4× faster than a comparable HashMap for enum keys.

Memory footprint comparison

CollectionOverhead for N=8 enum keys
HashSet / HashMapNode objects + hash table array
EnumSet1 long (8 bytes)
EnumMap1 Object[] of length 8

For small, fixed-domain key sets this difference is dramatic.


EnumSet vs HashSet — Quick Comparison

FeatureEnumSetHashSet
Key typeEnum onlyAny object
Backing storeBit vector (long)Hash table
PerformanceO(1), near zero overheadO(1) average, higher constant
Null elementsNot allowedOne null allowed
Iteration orderEnum declaration orderUnspecified
Thread safetyNot thread-safeNot thread-safe

EnumMap vs HashMap — Quick Comparison

FeatureEnumMapHashMap
Key typeEnum onlyAny object
Backing storeObject[] arrayHash table
PerformanceO(1) array indexO(1) average
Null keysNot allowedOne null allowed
Iteration orderEnum declaration orderUnspecified
MemoryCompact fixed arrayNode objects

When to Use Them

Use EnumSet when you need a set whose elements come from a fixed enum — permission flags, days of the week, feature toggles, state machines. It replaces the old int-bitmask pattern with something readable and type-safe.

Use EnumMap whenever your map keys are enum constants — routing tables, config-per-state, counting/grouping by category. Any time you would write Map<MyEnum, V>, prefer EnumMap<MyEnum, V>.

Tip: Prefer EnumMap and EnumSet over HashMap/HashSet any time your keys/elements are enums. The compiler enforces the correct types, your IDE autocompletes the constants, and the JVM runs the operations faster.


  • Enums — understand enum constants, ordinals, and methods before using these collections
  • Set Interface — the contract that EnumSet implements
  • Map Interface — the contract that EnumMap implements
  • HashSet — general-purpose set for non-enum elements
  • HashMap — general-purpose map; compare internals with EnumMap
  • Collections Utility Class — helper methods like Collections.synchronizedSet() that apply to EnumSet
Last updated June 13, 2026
Was this helpful?