What does EnumSet really mean?

From Joshua Bloch's book itself and in his own word:

The java.util package provides EnumSet class to efficiently represent sets of values drawn from a single enum type. This class implements the Set interface, providing all of the richness, type safety and interoperability you get with any other Set implementation. But internally, each EnumSet is represented as a bit vector. If the underlying enum type has sixty-four or fewer elements -- and most do -- the entire EnumSet is represented with a single long, so its performance is comparable to that of a bit field. Bulk operations, such as removeAll and retainAll, are implemented using bit wise arithmetic, just as you'll do manually for bit fields. But you are insulated from the ugliness and error-proneness of manual bit twiddling. The EnumSet does the hard work for you.

So we can do something like this.

public class SizeSet {

  public enum Size {S, M, L, XL, XXL, XXXL}

  public void applySize(Set<Size> sizes){}

}

Client Code calling it might do something like

SizeSet largeSizeSet = new SizeSet();
largeSizeSet.applySize(EnumSet.of(Size.L, Size.XXL, Size.XXL));

Note that the applySize method takes the Set<Size> rather than an EnumSet<Size>. While it is pretty obvious and likely that the client would pass an EnumSet to the method, it is a good practice to accept an interface rather than the concrete implementation.


Simplifying your code

EnumSet<Size> largeSize = EnumSet.of(Size.XXXL, Size.XXL, Size.XL, Size.L);
for(Size size: largeSize)
    System.out.print(size+" ");

You can see that largeSize is a regular Set except its designed to store Enums. How is that different? Firstly the JVM knows all the possible values of the set which means instead of storing all the objects it can use a bitmap where 1 means the item is present and 0 means it is not. This also means the order of the set is the order of the ordinal values i.e. the order they were defined. This is why this prints

L XL XXL XXXL

If you want to know more detail I suggest you read the source for this class.


A simple Enum is a list of values that you can only select one from at a time. Using your example, a size can be only one of S, M, L, etc for any given clothing. You could use simple constants instead of the Enum but this has its advantages of readability, easier maintenance and strict type checking.

An EnumSet will be used when you have the need for a variable to assume more than one Enum value at the same time. For instance, a font you write to screen with can be both bold and italic at the same time. An EnumSet will allow you to add the various values and to test whether one of those is actually set at any given time. If you have come to Java from other programming languages, this is the functionality usually called flags.

Compare the two:

enum Size { S, M, L, XL, XXL, XXXL }
Size currentSize;
...
currentSize = Size.S;
...
if (currentSize == Size.S) ...

defines, assigns and then checks for a single Enum value.

enum FontStyle { Bold, Italic, Underline, Strikethrough }
EnumSet<FontStyle> currentStyle;
...
currentStyle = EnumSet.of(FontStyle.Bold, FontStyle.Italic);
...
if (currentStyle.contains(FontStyle.Italic)) ...

defines, assigns two Enum values at the same time, then checks whether one of those is actually set or not.


As for any variable, its type is found in its declaration:

EnumSet largeSize

So yes, largeSize (which should be named largeSizes since it's a collection) is of type EnumSet. It should also be generified, and thus be declared as

EnumSet<Size> largeSizes

What it means, is that largeSizes is of type EnumSet. An EnumSet is a Set which contains enum instance of a specific enum type, in a more efficient way than other Set implementations (like HashSet, TreeSet, etc.). To know what an EnumSet is, read its API.