Java EnumSet


In Java, EnumSet is a specialized Set implementation designed specifically for use with enum types. Unlike general-purpose sets like HashSet or TreeSet, EnumSet is optimized for working with enum constants. It offers high performance and memory efficiency due to its use of bitwise operations and is the most efficient way to store a set of enum values.

In this article, we will explore the EnumSet class in Java, examining its features, benefits, and use cases. You will also see how to use EnumSet in practice with examples.


What is Java EnumSet?

EnumSet is a Set implementation that is specifically designed to work with enum types. It is part of the java.util package and is backed by a bit vector, which makes it extremely efficient when working with enum constants. The set is type-safe and guarantees that only enum values can be added to the set.

Key Features of EnumSet:

  • Optimized for Enums: It is the best choice when working with enums and provides better performance compared to other Set implementations.
  • Bitwise Representation: Internally, EnumSet uses a bit vector to represent enum constants, which ensures low memory overhead and fast performance.
  • Null Elements: Does not allow null elements.
  • Order: EnumSet maintains the natural ordering of the enum constants, based on their declaration order in the enum class.

EnumSet Methods

The EnumSet class implements all the standard methods defined by the Set interface. Here are some commonly used methods in EnumSet:

1. add(E e)

Adds the specified enum constant to the set. If the element already exists, it will not be added.

boolean add(E e);

2. remove(Object o)

Removes the specified enum constant from the set.

boolean remove(Object o);

3. contains(Object o)

Checks if the set contains the specified enum constant.

boolean contains(Object o);

4. size()

Returns the number of enum constants in the set

int size();

5. isEmpty()

Checks if the set is empty.

boolean isEmpty();

6. clear()

Removes all enum constants from the set.

void clear();

7. forEach(Consumer<? super E> action)

Performs the specified action for each enum constant in the set.

void forEach(Consumer<? super E> action);

8. range(E from, E to)

Creates an EnumSet that includes all the enum constants in the specified range.

static <E extends Enum<E>> EnumSet<E> range(E from, E to);

Creating EnumSet in Java

The EnumSet class provides a few static factory methods to create instances:

1. allOf(Class<E> elementType)

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

EnumSet<T> allOf(Class<T> elementType);

2. noneOf(Class<E> elementType)

Creates an empty EnumSet for the specified enum type.

EnumSet<T> noneOf(Class<T> elementType);

3. of(E e1, E e2, E... otherEnums)

Creates an EnumSet containing the specified enum constants.

EnumSet<T> of(E e1, E e2, E... otherEnums);

4. range(E from, E to)

Creates an EnumSet that includes all the constants in the specified range of enum values.

EnumSet<T> range(E from, E to);

Example: Using EnumSet in Java

Here’s a simple example demonstrating how to use EnumSet in Java:

import java.util.EnumSet;

enum Fruit {
    APPLE, BANANA, ORANGE, MANGO, GRAPE
}

public class EnumSetExample {
    public static void main(String[] args) {
        // Create an EnumSet containing all constants of the Fruit enum
        EnumSet<Fruit> allFruits = EnumSet.allOf(Fruit.class);
        System.out.println("All Fruits: " + allFruits);

        // Create an EnumSet with specific elements
        EnumSet<Fruit> someFruits = EnumSet.of(Fruit.APPLE, Fruit.ORANGE, Fruit.MANGO);
        System.out.println("Some Fruits: " + someFruits);

        // Create an EnumSet with a range of enum constants
        EnumSet<Fruit> fruitRange = EnumSet.range(Fruit.BANANA, Fruit.MANGO);
        System.out.println("Fruit Range: " + fruitRange);

        // Create an empty EnumSet
        EnumSet<Fruit> noFruits = EnumSet.noneOf(Fruit.class);
        System.out.println("No Fruits: " + noFruits);

        // Check if an element exists in the EnumSet
        System.out.println("Contains MANGO: " + someFruits.contains(Fruit.MANGO));

        // Remove an element
        someFruits.remove(Fruit.MANGO);
        System.out.println("After removal: " + someFruits);

        // Iterate through the EnumSet
        System.out.println("Iterating over EnumSet:");
        someFruits.forEach(fruit -> System.out.println(fruit));
    }
}

Output:

All Fruits: [APPLE, BANANA, ORANGE, MANGO, GRAPE]
Some Fruits: [APPLE, ORANGE, MANGO]
Fruit Range: [BANANA, ORANGE, MANGO]
No Fruits: []
Contains MANGO: true
After removal: [APPLE, ORANGE]
Iterating over EnumSet:
APPLE
ORANGE

Explanation:

  • allOf(Fruit.class) creates an EnumSet containing all enum constants of the Fruit enum.
  • of(Fruit.APPLE, Fruit.ORANGE, Fruit.MANGO) creates an EnumSet with specific enum constants.
  • range(Fruit.BANANA, Fruit.MANGO) creates an EnumSet with a range of enum constants.
  • noneOf(Fruit.class) creates an empty EnumSet.
  • The forEach() method iterates over all the elements of the EnumSet.

Advantages of Using EnumSet

  1. High Performance: EnumSet is much faster than other Set implementations like HashSet when working with enums. This is because it uses a bit vector, which is a very efficient representation.

  2. Memory Efficient: The internal structure of EnumSet is compact because it uses bitwise operations to store the enum values, leading to lower memory usage.

  3. Type-Safe: Since EnumSet is specifically designed for enums, it ensures type safety, meaning only valid enum values can be added to the set.

  4. Readability: Using EnumSet makes your code more readable and expressive when dealing with enum types, as it clearly shows that the set is specifically designed for enums.


When to Use EnumSet

You should consider using EnumSet when:

  1. Working with Enum Types: If you are dealing with enum constants and need a Set implementation.
  2. Performance and Memory Efficiency: If you need a fast and memory-efficient way to store and manipulate enum values.
  3. Bitwise Operations: If you need to perform bitwise operations on enum constants, as EnumSet supports this.
  4. No null Values: You don’t need to allow null values in the set.