JVM.GC.How EnumSet store data inside?

How EnumSet Stores Data Internally in Java

Unlike HashSet, which stores elements using a hash table (creating separate objects for each element), EnumSet stores enum values as bitwise flags inside a single long or long[] array, making it much more memory-efficient and faster.


1️⃣ How EnumSet Works Internally

  • EnumSet is an abstract class that has two main implementations:
    1. RegularEnumSet – Used when the enum has ≤ 64 values (stores elements in a single long bit field).
    2. JumboEnumSet – Used when the enum has > 64 values (stores elements in a long[] array).
  • Instead of storing separate objects, EnumSet represents each enum constant as a bit in a bitmask.

2️⃣ How RegularEnumSet Works (For ≤ 64 Enum Constants)

For enums with ≤ 64 elements, EnumSet uses a single long (64-bit field) to store the enum values.

Example: Enum with 3 Constants

import java.util.EnumSet;

enum Color { RED, GREEN, BLUE }

public class EnumSetExample {
    public static void main(String[] args) {
        EnumSet<Color> colors = EnumSet.of(Color.RED, Color.BLUE);
        System.out.println(colors); // Output: [RED, BLUE]
    }
}

How Is It Stored Internally?

  • Java assigns an ordinal value to each enum constant:
RED   = 0
GREEN = 1
BLUE  = 2

EnumSet represents them as bits in a long:

RED   = 1 << 0  (0001 in binary)
GREEN = 1 << 1  (0010 in binary)
BLUE  = 1 << 2  (0100 in binary)

The set {RED, BLUE} is stored as:

0001 (RED) 
0100 (BLUE)

EnumSet Bitwise Representation Example

EnumSet internally uses bitwise operations to store and manipulate enum values efficiently.


1️⃣ Understanding Bitwise Representation

Each enum constant has an ordinal value (its position in the enum declaration). EnumSet stores the set as a bitmask, where each bit represents an enum constant.

Example Enum

enum Color {
    RED,    // ordinal = 0
    GREEN,  // ordinal = 1
    BLUE,   // ordinal = 2
    YELLOW  // ordinal = 3
}

EnumSet represents each enum constant as a bit at the position of its ordinal value:

RED    = 1 << 0  → 0001 (binary)  = 1  (decimal)
GREEN  = 1 << 1  → 0010 (binary)  = 2  (decimal)
BLUE   = 1 << 2  → 0100 (binary)  = 4  (decimal)
YELLOW = 1 << 3  → 1000 (binary)  = 8  (decimal)

2️⃣ Creating an EnumSet and Checking Internal Representation

Let’s create an EnumSet and see how it is stored internally.

Example: Creating an EnumSet

import java.util.EnumSet;

public class EnumSetBitwiseExample {
    public static void main(String[] args) {
        EnumSet<Color> colors = EnumSet.of(Color.RED, Color.BLUE);

        int bitmask = getBitmask(colors);
        System.out.println("Bitmask: " + Integer.toBinaryString(bitmask)); // Print bitwise representation
    }

    private static int getBitmask(EnumSet<Color> set) {
        int mask = 0;
        for (Color c : set) {
            mask |= (1 << c.ordinal()); // Bitwise OR operation
        }
        return mask;
    }
}

Output

Bitmask: 101

Explanation

  • {RED, BLUE} corresponds to bit positions 0 and 2.
  • Bitwise OR (|) is used to set the bits
RED   → 0001 (1 in decimal)
BLUE  → 0100 (4 in decimal)
---------------------------
Combined (RED | BLUE) = 0101 (5 in decimal)

The output 101 (binary) confirms that RED (1st bit) and BLUE (3rd bit) are set.

3️⃣ Bitwise Operations in EnumSet

Adding an Element (Bitwise OR |)

If we add GREEN to {RED, BLUE}, it updates the bitmask:

colors.add(Color.GREEN);

New Bitmask Calculation

RED    = 0001  (1)
BLUE   = 0100  (4)
GREEN  = 0010  (2)
-----------------
Result  = 0111  (7)

New Bitmask: 7 (0111 in binary) → {RED, GREEN, BLUE}.

Removing an Element (Bitwise AND & Complement & ~)

If we remove RED, we update the bitmask:





colors.remove(Color.RED);
Current Set:   0111 (7)  →  {RED, GREEN, BLUE}
Remove RED:  ~0001 (NOT 1)
----------------------
New Bitmask:  0110 (6)  →  {GREEN, BLUE}

New Bitmask: 6 (0110 in binary) → {GREEN, BLUE}.

4️⃣ Why Is This Efficient?

  1. Takes only 1 long (64 bits) to store up to 64 enums.
  2. Bitwise operations (|, &, ~) are extremely fast (O(1) complexity).
  3. No hashing overhead like HashSet.

📌 Conclusion:
EnumSet uses bitwise operations internally to efficiently store, add, and remove elements. Instead of storing separate objects, it uses a single integer (long) as a bitmask to track which enums are in the set. 🚀

This entry was posted in Без рубрики. Bookmark the permalink.