enumset用位向量实现,每个枚举常量按声明顺序映射唯一bit位,≤64个时用单个long存储,>64个时用long数组,所有操作均为o(1)位运算。

EnumSet 用位向量(bit vector)高效存储枚举,核心是把每个枚举常量映射成一个独立的二进制位,整个集合状态就压缩在一个或多个 long 值里。
位向量怎么对应枚举常量
枚举类中常量按声明顺序编号:第一个是 ordinal=0,对应 bit 0(即 1L ),第二个是 ordinal=1,对应 bit 1(即 <code>1L ),以此类推。<br>
比如:
enum Status { PENDING, RUNNING, DONE }
-
PENDING→ bit 0 → 值为1L(二进制001) -
RUNNING→ bit 1 → 值为2L(二进制010) -
DONE→ bit 2 → 值为4L(二进制100)
集合 {PENDING, DONE} 的位向量就是 1L | 4L = 5L(二进制 101)。
内部怎么存:小枚举 vs 大枚举
- 枚举常量 ≤ 64 个:用单个
long elements字段,每位代表一个常量 - 超过 64 个:改用
long[] elements,每项管 64 位,索引由ordinal / 64算出,位偏移用ordinal % 64
这样既保证紧凑,又不牺牲可扩展性。
所有操作都是位运算,没有循环和对象分配
-
contains(e)→(elements & (1L -
add(e)→elements |= (1L -
remove(e)→elements &= ~(1L -
retainAll(other)→this.elements &= other.elements
这些全是 CPU 单指令操作,O(1),零装箱、零扩容、零哈希计算。
创建必须走静态工厂,不能 new
-
EnumSet.noneOf(Status.class)→ 返回空集合(elements = 0L) -
EnumSet.of(Status.PENDING, Status.DONE)→ 自动选RegularEnumSet,位或组合 -
EnumSet.allOf(Status.class)→ 把所有位设为 1(如 3 个常量 →0b111 = 7L) -
EnumSet.range(Status.PENDING, Status.RUNNING)→ 按 ordinal 连续填充位区间
JVM 根据参数个数自动选用 SingletonSet(1 个)、RegularEnumSet(2–64)、JumboEnumSet(>64),全程无冗余对象。
不复杂但容易忽略:它只认编译期确定的同一枚举类,且不允许 null —— 这些限制恰恰换来了极致效率。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











