Java

EnumSet and LinkedHashSet

Discover specialized set implementations that outperform general-purpose alternatives. EnumSet uses bit manipulation for blazing speed with enums, while LinkedHashSet preserves insertion order for predictable iteration.

πŸ“‹ At a Glance

AspectDetails
TopicEnumSet, LinkedHashSet, CopyOnWriteArraySet
ComplexityIntermediate
PrerequisitesPart 9 (HashSet Internals), Part 10 (TreeSet)
Time to Master2-3 hours
Interview FrequencyMedium (EnumSet performance, LinkedHashSet ordering)

🎯 What You'll Learn

After completing this article, you will be able to:

  1. Understand EnumSet's bit vector implementation and extreme performance
  2. Use LinkedHashSet for predictable iteration order
  3. Choose the right specialized set for your use case
  4. Leverage CopyOnWriteArraySet for concurrent read-heavy scenarios
  5. Combine specialized sets with proper design patterns

Production Story: The Permission System Memory Crisis

The Incident

Our user permission system was running out of memory. Each user had a Set of permissions, and with 100,000 active users, the JVM was struggling.

JAVA(19 lines)
Code
Loading syntax highlighter...

The Memory Problem

Let's calculate the memory usage:

JAVA(9 lines)
Code
Loading syntax highlighter...

The EnumSet Solution

JAVA(20 lines)
Code
Loading syntax highlighter...

How EnumSet Works

TEXT(21 lines)
Code
Loading syntax highlighter...

Performance Comparison

JAVA(13 lines)
Code
Loading syntax highlighter...

Lessons Learned

  1. EnumSet is always better than HashSet - no exceptions
  2. Bit manipulation is faster than hashing
  3. Memory savings compound with many instances
  4. Check your enum sets - easy performance win

Mental Model: The Specialized Set Family

TEXT(34 lines)
Code
Loading syntax highlighter...

Deep Dive: EnumSet Internals

RegularEnumSet vs JumboEnumSet

JAVA(13 lines)
Code
Loading syntax highlighter...

RegularEnumSet Implementation

JAVA(28 lines)
Code
Loading syntax highlighter...

EnumSet Factory Methods

JAVA(20 lines)
Code
Loading syntax highlighter...

EnumSet vs HashSet Performance

JAVA(29 lines)
Code
Loading syntax highlighter...

Deep Dive: LinkedHashSet

Predictable Iteration Order

JAVA(13 lines)
Code
Loading syntax highlighter...

LinkedHashSet Internals

JAVA(20 lines)
Code
Loading syntax highlighter...

LinkedHashSet Use Cases

JAVA(20 lines)
Code
Loading syntax highlighter...

LinkedHashSet vs TreeSet for Order

JAVA(18 lines)
Code
Loading syntax highlighter...

Deep Dive: CopyOnWriteArraySet

Thread-Safe Without Locks

JAVA(13 lines)
Code
Loading syntax highlighter...

When to Use CopyOnWriteArraySet

JAVA(17 lines)
Code
Loading syntax highlighter...

CopyOnWriteArraySet Performance

JAVA(18 lines)
Code
Loading syntax highlighter...

Deep Dive: Choosing the Right Set

Decision Matrix

ScenarioBest ChoiceWhy
Enum valuesEnumSet10x faster, 10x less memory
Need insertion orderLinkedHashSetO(1) ops + order
Need sorted orderTreeSetO(log n) ops + sorted
Default choiceHashSetO(1) ops, good general
Concurrent, read-heavyCopyOnWriteArraySetNo locks on read
Concurrent, write-heavyConcurrentHashMap.newKeySet()Better write scaling
Immutable setSet.of()Truly immutable

Performance Characteristics

TEXT(10 lines)
Code
Loading syntax highlighter...

Memory Footprint

JAVA(9 lines)
Code
Loading syntax highlighter...

⚠️ Common Mistakes

Mistake 1: Using HashSet Instead of EnumSet

JAVA(12 lines)
Code
Loading syntax highlighter...

Mistake 2: Forgetting LinkedHashSet Order Guarantee

JAVA(13 lines)
Code
Loading syntax highlighter...

Mistake 3: CopyOnWriteArraySet for Large Sets

JAVA(12 lines)
Code
Loading syntax highlighter...

Mistake 4: EnumSet.of() with No Arguments

JAVA(9 lines)
Code
Loading syntax highlighter...

Mistake 5: Modifying Set During Iteration

JAVA(21 lines)
Code
Loading syntax highlighter...

πŸ› Debug This

Challenge 1: The Disappearing Elements

JAVA(9 lines)
Code
Loading syntax highlighter...
βœ… Answer:

Output:

TEXT(2 lines)
Code
Loading syntax highlighter...
This works fine! EnumSet is mutable and supports all Set operations. The reference days still points to the same EnumSet.

Challenge 2: The Order Mystery

JAVA(8 lines)
Code
Loading syntax highlighter...
βœ… Answer:
Output: [3, 2, 1]

LinkedHashSet preserves insertion order. When you remove and re-add an element, it goes to the end (new insertion position).

Challenge 3: The Concurrent Puzzle

JAVA(10 lines)
Code
Loading syntax highlighter...
βœ… Answer:

Output:

TEXT(2 lines)
Code
Loading syntax highlighter...

CopyOnWriteArraySet iteration uses a snapshot. The iterator sees all three elements from the snapshot, while the actual set is being emptied. No ConcurrentModificationException because iterator and modifications work on different arrays.


πŸ’» Exercises

Exercise 1: Permission Checker

Create an efficient permission system using EnumSet:

JAVA(5 lines)
Code
Loading syntax highlighter...
βœ… Solution:
JAVA(22 lines)
Code
Loading syntax highlighter...

Exercise 2: Ordered Deduplicator

Create a utility that deduplicates while preserving first occurrence order:

JAVA
Code
Loading syntax highlighter...
βœ… Solution:
JAVA(7 lines)
Code
Loading syntax highlighter...

Exercise 3: Feature Toggle System

Create a thread-safe feature toggle system:

JAVA(6 lines)
Code
Loading syntax highlighter...
βœ… Solution:
JAVA(20 lines)
Code
Loading syntax highlighter...

Exercise 4: EnumSet Serialization

Create utilities to serialize/deserialize EnumSet to/from a bitmask:

JAVA(4 lines)
Code
Loading syntax highlighter...
βœ… Solution:
JAVA(26 lines)
Code
Loading syntax highlighter...

Exercise 5: LRU Cache Using LinkedHashSet

Implement a simple LRU (Least Recently Used) set with max capacity:

JAVA(6 lines)
Code
Loading syntax highlighter...
βœ… Solution:
JAVA(30 lines)
Code
Loading syntax highlighter...

🎀 Senior-Level Interview Questions

Question 1: EnumSet Performance

Q: Why is EnumSet faster than HashSet for enum values?
A:

EnumSet uses bit manipulation instead of hashing:

  1. Storage: Single long (or long[]) vs HashMap with Entry objects
  2. add/contains: Single bit operation vs hash + equals + bucket lookup
  3. Set operations: Single bitwise AND/OR vs element-by-element iteration
JAVA(7 lines)
Code
Loading syntax highlighter...

Question 2: LinkedHashSet vs LinkedHashMap

Q: How is LinkedHashSet implemented and how does it relate to LinkedHashMap?
A:

LinkedHashSet extends HashSet but uses LinkedHashMap as its backing store:

JAVA(7 lines)
Code
Loading syntax highlighter...

Key points:

  • LinkedHashSet delegates to LinkedHashMap
  • Elements are keys in the map, value is a dummy PRESENT object
  • The linked list is through the map entries, not separate nodes

Question 3: CopyOnWriteArraySet Trade-offs

Q: What are the trade-offs of CopyOnWriteArraySet vs other concurrent set options?
A:
AspectCopyOnWriteArraySetConcurrentHashMap.newKeySet()
Read performanceO(n) containsO(1) contains
Write performanceO(n) - copies arrayO(1) amortized
Memory on write2x during copyStable
Iteration consistencySnapshot (stale)Weakly consistent
Best forSmall, read-heavyLarge, any pattern
JAVA(7 lines)
Code
Loading syntax highlighter...

Question 4: EnumSet.allOf() vs new HashSet(Arrays.asList())

Q: What's the difference between these two approaches for creating a set of all enum values?
A:
JAVA(14 lines)
Code
Loading syntax highlighter...

Question 5: Ordering Guarantees

Q: Explain the iteration order guarantees of different Set implementations.
A:
Set TypeIteration Order
HashSetUndefined (based on hash buckets)
LinkedHashSetInsertion order (first add wins)
TreeSetSorted order (natural or Comparator)
EnumSetDeclaration order (enum ordinal)
CopyOnWriteArraySetInsertion order
JAVA(4 lines)
Code
Loading syntax highlighter...

Question 6: EnumSet.copyOf() Edge Case

Q: What happens if you call EnumSet.copyOf() on an empty collection?
A:
JAVA(16 lines)
Code
Loading syntax highlighter...

πŸ“ Summary & Key Takeaways

EnumSet

  • Always use for enum values (no exceptions!)
  • Uses bit vector: O(1) operations, minimal memory
  • RegularEnumSet (≀64 values) vs JumboEnumSet (>64)
  • Factory methods: allOf, noneOf, of, range, complementOf

LinkedHashSet

  • Preserves insertion order
  • O(1) operations like HashSet
  • ~40% memory overhead for order tracking
  • Use for ordered deduplication

CopyOnWriteArraySet

  • Thread-safe through copying
  • O(n) contains (not hash-based!)
  • Best for small, read-heavy, rarely modified sets
  • Iteration never throws ConcurrentModificationException

Decision Guidelines

  • Enums β†’ EnumSet (always)
  • Need order β†’ LinkedHashSet (insertion) or TreeSet (sorted)
  • Concurrent + small + read-heavy β†’ CopyOnWriteArraySet
  • Concurrent + general β†’ ConcurrentHashMap.newKeySet()
  • Default β†’ HashSet

🏁 Conclusion

Specialized set implementations exist because one size doesn't fit all. EnumSet demonstrates how understanding your data type enables dramatic optimization - 10x performance improvement is just a class swap away.

Key takeaways:

  1. EnumSet is always better than HashSet for enums - make it a habit
  2. LinkedHashSet costs ~40% more memory but provides predictable order
  3. CopyOnWriteArraySet has O(n) contains - don't use for large sets
  4. Choose based on characteristics - order, thread-safety, element type
  5. Measure when unsure - theoretical wins don't always materialize

In the next article, we'll explore HashMap internals deeply - the bucket array, hash distribution, and resize mechanics that power Java's most-used collection.


πŸ“… Review Schedule

To solidify your understanding, review this material:

  • Tomorrow: Re-read EnumSet bit manipulation details
  • In 3 days: Implement Exercise 4 (EnumSet Serialization) again
  • In 1 week: Explain EnumSet vs HashSet tradeoffs to a colleague
  • In 2 weeks: Review the permission system production story