Learnitweb

Java EnumSet

The EnumSet class in Java is a specialized Set implementation designed specifically for use with enum types. It is part of the java.util package and provides a highly efficient, compact representation of sets of enum constants.

Unlike general-purpose sets like HashSet or TreeSet, EnumSet is optimized for enums in both performance and memory usage.

1. Overview of EnumSet

  • Definition: EnumSet<E extends Enum<E>> is a specialized Set implementation for enum types.
  • Characteristics:
    1. Only works with enum types; cannot store other objects.
    2. Maintains elements in natural order, i.e., the order in which they are declared in the enum.
    3. Implements AbstractSet and Serializable.
    4. Highly memory efficient – internally represented as a bit vector.
    5. All operations are O(1) in time complexity for most cases.
  • Hierarchy:
java.lang.Object
   -> java.util.AbstractSet<E>
       -> java.util.EnumSet<E>
  • Unlike HashSet or TreeSet, EnumSet cannot contain null elements. Attempting to add null will throw NullPointerException.

2. Creating an EnumSet

EnumSet provides several static factory methods for creating sets:

2.1 allOf(Class<E> elementType)

Creates an EnumSet containing all enum constants of the specified type.

enum Color { RED, GREEN, BLUE }

EnumSet<Color> allColors = EnumSet.allOf(Color.class);
System.out.println(allColors); // [RED, GREEN, BLUE]

2.2 noneOf(Class<E> elementType)

Creates an empty EnumSet of the specified enum type.

EnumSet<Color> noColors = EnumSet.noneOf(Color.class);
System.out.println(noColors); // []

2.3 of(E first, E... rest)

Creates an EnumSet containing specified elements.

EnumSet<Color> someColors = EnumSet.of(Color.RED, Color.BLUE);
System.out.println(someColors); // [RED, BLUE]

2.4 range(E from, E to)

Creates an EnumSet containing all elements between the two specified elements, inclusive.

EnumSet<Color> rangeColors = EnumSet.range(Color.RED, Color.GREEN);
System.out.println(rangeColors); // [RED, GREEN]

2.5 copyOf(Collection<E> c)

Creates an EnumSet containing the elements of the given collection.

List<Color> list = Arrays.asList(Color.RED, Color.BLUE);
EnumSet<Color> copySet = EnumSet.copyOf(list);
System.out.println(copySet); // [RED, BLUE]

3. Adding and Removing Elements

EnumSet supports the usual Set operations like add, remove, contains, etc.

EnumSet<Color> colors = EnumSet.noneOf(Color.class);
colors.add(Color.RED);
colors.add(Color.GREEN);
System.out.println(colors); // [RED, GREEN]

colors.remove(Color.RED);
System.out.println(colors); // [GREEN]

System.out.println(colors.contains(Color.BLUE)); // false

4. Bulk Operations

EnumSet supports bulk operations similar to other Set implementations:

  • addAll(Collection<E> c) – Adds all elements from another collection.
  • removeAll(Collection<E> c) – Removes all elements found in the specified collection.
  • retainAll(Collection<E> c) – Keeps only the elements found in the specified collection.
  • containsAll(Collection<E> c) – Checks if all elements exist.
EnumSet<Color> set1 = EnumSet.of(Color.RED, Color.GREEN);
EnumSet<Color> set2 = EnumSet.of(Color.GREEN, Color.BLUE);

set1.addAll(set2);
System.out.println(set1); // [RED, GREEN, BLUE]

set1.removeAll(EnumSet.of(Color.RED));
System.out.println(set1); // [GREEN, BLUE]

set1.retainAll(EnumSet.of(Color.BLUE));
System.out.println(set1); // [BLUE]

5. Iterating Over EnumSet

EnumSet maintains natural order, so iteration is predictable.

EnumSet<Color> colors = EnumSet.allOf(Color.class);
for (Color color : colors) {
    System.out.println(color);
}

// Output:
// RED
// GREEN
// BLUE
  • You can also use forEach with a lambda:
colors.forEach(c -> System.out.println(c.name() + " ordinal: " + c.ordinal()));

6. Set Operations

EnumSet provides efficient set operations:

  • unionaddAll()
  • intersectionretainAll()
  • differenceremoveAll()
EnumSet<Color> set1 = EnumSet.of(Color.RED, Color.GREEN);
EnumSet<Color> set2 = EnumSet.of(Color.GREEN, Color.BLUE);

EnumSet<Color> union = EnumSet.copyOf(set1);
union.addAll(set2);
System.out.println(union); // [RED, GREEN, BLUE]

EnumSet<Color> intersection = EnumSet.copyOf(set1);
intersection.retainAll(set2);
System.out.println(intersection); // [GREEN]

EnumSet<Color> difference = EnumSet.copyOf(set1);
difference.removeAll(set2);
System.out.println(difference); // [RED]

7. Performance Characteristics

  1. Memory Efficient: Internally uses a bit vector, so it is much smaller than HashSet for enums.
  2. Fast Operations: Most operations like add, remove, contains are O(1).
  3. Iteration Order: Always follows enum declaration order.
  4. Cannot Contain Null: Adding null throws NullPointerException.

8. Use Cases of EnumSet

  1. Flag Handling: Represent multiple options or flags efficiently.
    Example: User permissions, feature toggles.
enum Permission { READ, WRITE, EXECUTE }
EnumSet<Permission> perms = EnumSet.of(Permission.READ, Permission.WRITE);
  1. Finite State Machines: Represent sets of states in an enum.
  2. Efficient Lookup: Store enum constants with high performance, low memory overhead.
  3. Set Operations: Efficient union, intersection, and difference of enum sets.

9. Summary

EnumSet is a highly optimized Set implementation for enum types in Java:

  • Only works with enums; cannot store nulls.
  • Maintains elements in natural order.
  • Provides factory methods like allOf, noneOf, of, range, copyOf.
  • Supports bulk operations, iteration, and standard set operations.
  • Extremely memory and performance efficient, using a bit vector internally.
  • Ideal for flags, state machines, and operations on enum constants.