Have you ever used Java standard class EnumSet
in real-life applications? Me neither. Nevertheless, it can be useful in some cases.
EnumSet
is an abstract Set
which can hold enum values only. And if you are about to store enum values in a Set
, you should always use EnumSet
because it is usually faster and takes less memory. These benefits are achieved by storing data as a bit vector in one of two EnumSet
implementations:
-
long
bit vector inRegularEnumSet
for enum types with 64 or fewer enum constants, -
long[]
bit vector inJumboEnumSet
for enum types with more than 64 elements.
But enough talking, let's see it in action!
Here we have an enum of quotes:
@Getter
@AllArgsConstructor
public enum Quote {
DONT_PANIC("Don't Panic."),
THE_ANSWER("42"),
TOWEL("A towel is about the most massively useful thing an interstellar hitchhiker can have."),
SO_LONG("So long, and thanks for all the fish."),
;
private final String value;
}
Here is how we can create EnumSet
:
EnumSet<Quote> allQuotes = EnumSet.allOf(Quote.class);
EnumSet<Quote> noQuotes = EnumSet.noneOf(Quote.class);
EnumSet<Quote> twoQuotes = EnumSet.of(Quote.DONT_PANIC, Quote.TOWEL);
EnumSet<Quote> threeQuotes = EnumSet.range(Quote.DONT_PANIC, Quote.TOWEL);
EnumSet<Quote> sameThreeQuotes = EnumSet.complementOf(EnumSet.of(Quote.SO_LONG));
allQuotes
contains all the enum elements, while noQuotes
is empty.
twoQuotes
contains two listed elements, while both threeQuotes
and sameThreeQuotes
contain the set of the first three elements of the Quotes
enum.
Now, you can use all the standard operations with these sets, e.g. add
, remove
, contains
, etc.
Dream your code, code your dream.
Top comments (2)
EnumSet handy API probably the only legit reason to prefer it over Set.
This is called premature optimisation, and developers should consider speed and memory consumption only if it’s hot place in the app, otherwise it’s just bringing additional complexity which we could avoid. The only exception of this rule is mobile app.
Set
is an interface, whileEnumSet
is an implementation of that interface. So I'm confused about your statement concerning preference of one over the other. They are not alternatives of each other.Second, your quote from the post cut off a key part of the author's original sentence. The author of the post isn't claiming that you should always use
EnumSet
in general. They are claiming that strictly for the case of a set of enum values.Also, choosing to use
EnumSet
for a set of enum values, rather than let's say aHashSet
or aTreeSet
, is not an example of premature optimization. It is a sound choice of data structure for the specified context. It also does not increase code complexity at all. It implements the exact same interface,Set
, as the alternatives. Other than instantiating an instance ofEnumSet
rather than an instance of one of the otherSet
implementations, all other code would be the same. No additional code complexity caused by usingEnumSet
vs any of the alternatives.Premature optimization would be if he was suggesting using a
long
directly and using bitwise operations for adding elements, removing elements, and checking for containment, etc in order to avoid method calls. That would add unnecessary code complexity for no substantive gain. But that isn't what he is suggesting. Choosing to use anEnumSet
to represent a set of values of an enum type is just making an informed and wise choice of data structure from among the available options for doing so.