EnumSets and EnumMaps in Java: High-Performance Collections for Enums

Illustration for EnumSets and EnumMaps in Java: High-Performance Collections for Enums
By Last updated:

A common mistake developers make when working with Enums is to use regular HashSet or HashMap for storing Enum constants. While these work, they’re inefficient compared to purpose-built collections. Developers end up with unnecessary memory overhead and slower performance, especially when working with frequent Enum lookups or large collections.

This is where EnumSet and EnumMap come in. These are specialized, high-performance collections designed specifically for Enums. They are backed by bit vectors (for EnumSet) and arrays indexed by Enum ordinals (for EnumMap), making them faster and more memory-efficient than general-purpose collections.

Think of Enums as VIPs in a club: EnumSet is like an exclusive guest list where presence is tracked with a checkbox system (bit vector), and EnumMap is like a personalized locker room where each Enum constant has its own reserved locker (array slot).


EnumSet: A Specialized Set for Enums

EnumSet is a high-performance Set implementation for Enums. It stores Enum values as bit vectors, making operations like add, remove, and contains O(1) and extremely fast.

Example: Working Days

import java.util.EnumSet;

public enum Day {
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}

public class EnumSetExample {
    public static void main(String[] args) {
        EnumSet<Day> workDays = EnumSet.range(Day.MONDAY, Day.FRIDAY);
        System.out.println(workDays); // [MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY]

        workDays.add(Day.SATURDAY);
        System.out.println(workDays); // [MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY]
    }
}

Key Features of EnumSet

  • Backed by bit vectors → memory-efficient.
  • Iteration order follows Enum declaration order.
  • Provides factory methods: of(), range(), allOf(), noneOf().
  • Not thread-safe (wrap with Collections.synchronizedSet() if needed).

EnumMap: A Specialized Map for Enums

EnumMap is a high-performance Map implementation where keys are Enum constants. It stores mappings internally as an array indexed by the Enum’s ordinal().

Example: Order Status Messages

import java.util.EnumMap;

public enum OrderStatus {
    NEW, PROCESSING, SHIPPED, DELIVERED, CANCELLED
}

public class EnumMapExample {
    public static void main(String[] args) {
        EnumMap<OrderStatus, String> statusMessages = new EnumMap<>(OrderStatus.class);
        statusMessages.put(OrderStatus.NEW, "Order received.");
        statusMessages.put(OrderStatus.SHIPPED, "Your order is on the way!");
        statusMessages.put(OrderStatus.DELIVERED, "Order completed.");

        System.out.println(statusMessages.get(OrderStatus.SHIPPED)); // Your order is on the way!
    }
}

Key Features of EnumMap

  • Backed by an array → faster than HashMap.
  • Keys must be from a single Enum type.
  • Maintains natural Enum order.
  • Null keys are not allowed, but null values are permitted.

Real-World Use Case: Access Control with EnumMap and EnumSet

import java.util.EnumMap;
import java.util.EnumSet;

public enum Role { ADMIN, USER, GUEST }

public class AccessControl {
    public static void main(String[] args) {
        EnumMap<Role, EnumSet<String>> permissions = new EnumMap<>(Role.class);

        permissions.put(Role.ADMIN, EnumSet.of("READ", "WRITE", "DELETE"));
        permissions.put(Role.USER, EnumSet.of("READ", "WRITE"));
        permissions.put(Role.GUEST, EnumSet.of("READ"));

        System.out.println("Admin permissions: " + permissions.get(Role.ADMIN));
    }
}

This is efficient and avoids the overhead of generic maps and sets.


Best Practices and Pitfalls

  • Use EnumSet when you need a Set of Enum constants—it’s faster than HashSet.
  • Use EnumMap when mapping Enum keys—it’s faster and more memory-efficient than HashMap.
  • Don’t use Enums from multiple types in the same EnumMap—it supports only one type.
  • Be cautious with concurrency—wrap collections for thread-safety if needed.

📌 What's New in Java for Enum Collections?

  • Java 5 – EnumSet and EnumMap introduced.
  • Java 8 – Streams and lambdas integrate smoothly with EnumSet and EnumMap. Example:
    EnumSet.allOf(Day.class).forEach(System.out::println);
    
  • Java 9 – Module restrictions; no major changes for EnumSet/EnumMap.
  • Java 17 – Sealed classes complement Enums but don’t directly affect collections.
  • Java 21 – Switch pattern matching works with Enums, indirectly aiding Enum-based collections.

Summary + Key Takeaways

  • EnumSet and EnumMap are specialized, high-performance collections for Enums.
  • They are faster and more memory-efficient than HashSet and HashMap.
  • Use EnumSet for sets of Enum values, and EnumMap when mapping keys to values.
  • They preserve Enum ordering and integrate seamlessly with modern Java features.
  • Think of EnumSet as a bit vector guest list and EnumMap as a locker room for constants.

FAQ: EnumSet and EnumMap in Java

Q1. Why use EnumSet instead of HashSet?
Because EnumSet uses bit vectors, making it faster and more memory-efficient.

Q2. Can EnumSet hold null values?
No, EnumSet does not allow nulls.

Q3. Why use EnumMap instead of HashMap?
EnumMap uses arrays indexed by ordinals, giving better performance.

Q4. Can EnumMap accept null keys?
No, null keys are not permitted.

Q5. Do EnumSet and EnumMap maintain order?
Yes, they maintain Enum declaration order.

Q6. Are EnumSet and EnumMap thread-safe?
No, wrap them with synchronized wrappers if thread-safety is required.

Q7. Can I use EnumSet with multiple Enum types?
No, EnumSet works with a single Enum type at a time.

Q8. Can EnumMap store duplicate values?
Yes, values can repeat, but keys (Enum constants) are unique.

Q9. How do EnumSet and EnumMap integrate with Streams?
They work seamlessly with Stream APIs for filtering, mapping, etc.

Q10. What happens if I reorder Enum constants?
EnumSet and EnumMap rely on ordinals internally, but they remain consistent since ordinals are tied to declaration order.

Q11. Are these collections suitable for persistence?
Yes, they can be serialized, but persistence frameworks usually store Enum names, not collections.

Q12. Any major updates to EnumSet/EnumMap after Java 5?
No significant updates—their core functionality has remained stable.