library
intermediateEnumSet & EnumMap
Use specialized, high-performance collections for enum keys/elements instead of HashSet/HashMap.
These two exploit one fact: enum constants have consecutive ordinals, so no hashing is needed.
EnumMap = a fixed-size mailbox row (one slot per apartment/enum). You go directly to slot 3 for enum ordinal 3. HashMap = a post office with hash lookups — much more overhead for a small, fixed set of keys.
Key Concepts
1
EnumSet<Day> weekend = EnumSet.of(Day.SAT, Day.SUN);
EnumMap<Day, String> hours = new EnumMap<>(Day.class);
hours.put(Day.MON, "9-5");2
EnumSet is a bit vector. One long, one bit per constant, so membership is a bitwise AND:
EnumSetlong
3
contains O(1), a single bit test
add O(1)
union, intersection O(1) for the whole set4
That makes it both faster and far smaller than a HashSet — no node objects, no hash computation, no
collision handling.
HashSet
5
EnumMap is a plain array indexed by ordinal(). get is one array access, with no hashing and no
collisions.
EnumMapordinal()get
6
The factory methods are the nice part of EnumSet.
EnumSet.of(READ, WRITE)
EnumSet.allOf(Day.class) every constant
EnumSet.noneOf(Day.class) empty, correctly typed
EnumSet.range(MON, FRI) a declaration-order range
EnumSet.complementOf(weekend) everything elseEnumSet
7
complementOf and range have no equivalent in the general collections, and both read far better than
the loop you would write.
complementOfrange
8
Use it instead of a bitmask.
int perms = READ | WRITE; // what type is this? any int
EnumSet<Perm> perms = EnumSet.of(READ, WRITE); // type-safe, printable9
The bitmask is the traditional trick for a compact flag set. EnumSet is just as compact and cannot be
passed a meaningless value.
EnumSet
10
Iteration follows declaration order, not insertion, for both classes. So reordering your enum
constants changes iteration order — one more reason never to persist ordinal().
ordinal()
11
Null rules. EnumSet rejects null entirely. EnumMap rejects a null key and allows a null value.
EnumSetEnumMap
12
And the 64-constant boundary, if you are asked: up to 64 constants EnumSet uses a single long
(RegularEnumSet); beyond that a long[] (JumboEnumSet). Both are O(1).
EnumSetlongRegularEnumSetlong[]JumboEnumSet
13
What the interviewer is probing.1. "Why are these faster than HashSet and HashMap?" Probing: the implementation. Stalls:
"They are optimised." Moves up: EnumSet is a bit vector and EnumMap an array indexed by ordinal —
no hashing, no collisions, no boxing.
14
2. "What should you use instead of an int bitmask for flags?" Probing: the modern replacement.
Stalls: "Bitmasks are fine." Moves up: EnumSet.of(READ, WRITE) — as compact, type-safe,
printable, and it cannot be passed a meaningless value.
15
3. "What order does iteration follow?" Probing: the ordering guarantee. Stalls: "Insertion
order." Moves up: declaration order of the enum — which is another reason reordering constants is
risky.
16
4. "Which factory methods are worth knowing?" Probing: the API. Stalls: "Just of." *Moves
up:* allOf, noneOf, range and complementOf — none of which have an equivalent in the general
collections.