When working with fixed categories such as permissions, statuses, or configuration options, Enums are one of Java’s most useful features. But often, you need to combine multiple Enum values — for example, a user with multiple permissions or a device that supports several protocols.
In such cases, you can use a Set of Enums, and the most efficient implementation is EnumSet.
This guide explains, step by step, how to:
- Define an Enum
- Create and populate a Set of Enums
- Iterate over EnumSets
- Compare EnumSet with other Set types
- Use EnumSets in real-world scenarios
1. Defining an Enum in Java
An Enum represents a fixed collection of constants.
Here’s a simple example:
public enum MyEnum {
CONSTANT1,
CONSTANT2,
CONSTANT3
}
Each constant (CONSTANT1, CONSTANT2, CONSTANT3) is an instance of MyEnum.
You can also add fields and methods to an Enum:
public enum Priority {
LOW(1),
MEDIUM(2),
HIGH(3);
private final int level;
Priority(int level) {
this.level = level;
}
public int getLevel() {
return level;
}
}
2. Creating a Set of Enum Values
The simplest way to create a Set of Enum values is by using EnumSet:
import java.util.EnumSet;
import java.util.Set;
public class EnumSetExample {
public static void main(String[] args) {
// Create an empty EnumSet
Set<MyEnum> mySet = EnumSet.noneOf(MyEnum.class);
// Add Enum values
mySet.add(MyEnum.CONSTANT1);
mySet.add(MyEnum.CONSTANT2);
System.out.println("EnumSet values: " + mySet);
}
}
Output:
EnumSet values: [CONSTANT1, CONSTANT2]
3. Initialize an EnumSet with Specific Values
You can create a pre-populated EnumSet with EnumSet.of():
Set<MyEnum> mySet = EnumSet.of(MyEnum.CONSTANT1, MyEnum.CONSTANT3);
You can even add more values later:
mySet.add(MyEnum.CONSTANT2);
System.out.println(mySet); // [CONSTANT1, CONSTANT2, CONSTANT3]
4. Create a Set with All Enum Values
If you want a Set containing all constants from an Enum, use EnumSet.allOf():
Set<MyEnum> allValues = EnumSet.allOf(MyEnum.class);
System.out.println("All Enum values: " + allValues);
Output:
All Enum values: [CONSTANT1, CONSTANT2, CONSTANT3]
5. Remove Elements from an EnumSet
Removing elements is as easy as adding them:
allValues.remove(MyEnum.CONSTANT2);
System.out.println("After removal: " + allValues);
Output:
After removal: [CONSTANT1, CONSTANT3]
6. Iterate Over EnumSet Elements
You can iterate through an EnumSet using an enhanced for-loop:
for (MyEnum value : allValues) {
System.out.println("Processing: " + value);
}
Or use Java Streams:
allValues.stream().forEach(System.out::println);
7. EnumSet Range Example
When Enum constants have a defined order, you can create a range of values:
Set<Priority> mediumToHigh = EnumSet.range(Priority.MEDIUM, Priority.HIGH);
System.out.println("Range: " + mediumToHigh);
Output:
Range: [MEDIUM, HIGH]
8. Combining and Complementing EnumSets
You can perform set operations easily:
EnumSet<MyEnum> setA = EnumSet.of(MyEnum.CONSTANT1, MyEnum.CONSTANT2);
EnumSet<MyEnum> setB = EnumSet.of(MyEnum.CONSTANT2, MyEnum.CONSTANT3);
// Union
EnumSet<MyEnum> union = EnumSet.copyOf(setA);
union.addAll(setB);
System.out.println("Union: " + union);
// Intersection
EnumSet<MyEnum> intersection = EnumSet.copyOf(setA);
intersection.retainAll(setB);
System.out.println("Intersection: " + intersection);
// Complement
EnumSet<MyEnum> complement = EnumSet.complementOf(setA);
System.out.println("Complement of setA: " + complement);
Output:
Union: [CONSTANT1, CONSTANT2, CONSTANT3]
Intersection: [CONSTANT2]
Complement of setA: [CONSTANT3]
9. Real-World Example: User Permissions
Let’s see a practical use case — assigning multiple permissions to a user:
public enum Permission {
READ,
WRITE,
EXECUTE
}
public class User {
private String username;
private EnumSet<Permission> permissions;
public User(String username) {
this.username = username;
this.permissions = EnumSet.noneOf(Permission.class);
}
public void grant(Permission permission) {
permissions.add(permission);
}
public void revoke(Permission permission) {
permissions.remove(permission);
}
public boolean hasPermission(Permission permission) {
return permissions.contains(permission);
}
@Override
public String toString() {
return username + " permissions: " + permissions;
}
public static void main(String[] args) {
User user = new User("Alice");
user.grant(Permission.READ);
user.grant(Permission.WRITE);
System.out.println(user);
user.revoke(Permission.WRITE);
System.out.println(user);
System.out.println("Has EXECUTE? " + user.hasPermission(Permission.EXECUTE));
}
}
Output:
Alice permissions: [READ, WRITE]
Alice permissions: [READ]
Has EXECUTE? false
10. EnumSet vs HashSet
| Feature | EnumSet | HashSet |
|---|---|---|
| Performance | Very fast (bit vector) | Slower (hash-based) |
| Memory Usage | Low | Higher |
| Allows null | ❌ No | ✅ Yes |
| Type Safety | ✅ Only one Enum type | Generic |
| Natural Order | ✅ Maintains declaration order | ❌ No guarantee |
For Enum types, always prefer EnumSet.
11. Example Using a Regular Set (for Comparison)
import java.util.HashSet;
import java.util.Set;
Set<MyEnum> hashSet = new HashSet<>();
hashSet.add(MyEnum.CONSTANT1);
hashSet.add(MyEnum.CONSTANT2);
System.out.println(hashSet);
Although this works, it’s less efficient and doesn’t guarantee Enum order.
✅ Conclusion
When working with multiple Enum values, EnumSet provides the cleanest, fastest, and safest solution in Java.
It’s ideal for:
- Managing feature flags
- Handling user roles or permissions
- Representing configuration options
- Grouping related Enum constants
With its compact memory representation and intuitive methods, EnumSet is the best practice for handling Enum collections in Java.
🔑 Key Takeaways
- Use
EnumSet.noneOf()for an empty set. - Use
EnumSet.of()for predefined values. - Use
EnumSet.allOf()to include all Enum constants. - Use
EnumSet.range()for ordered subsets. - Prefer EnumSet over HashSet for Enums — faster and type-safe.


