EnumSet 用位运算管理枚举,以 long 位向量替代对象存储,实现轻量、高速的集合操作。它仅支持同一枚举类型,天然支持位级交并补运算,适用于状态组合、权限开关等固定枚举场景。

用 EnumSet 管理枚举,本质是用位运算代替对象存储和哈希查找,所以更轻、更快——它不存对象引用,只记“开/关”状态。
底层靠位向量,不是对象数组
EnumSet 内部不用 new 出一堆枚举实例来塞进集合,而是把每个枚举值映射到一个 bit 位:ordinal=0 → 第 0 位,ordinal=1 → 第 1 位……最多 64 个时,只用一个 long(8 字节)就能表示全部存在性。比如 EnumSet.of(Color.RED, Color.BLUE) 在内存里可能就是 0b11(假设 RED 是 0、BLUE 是 1)。而 HashSet 至少要存两个对象引用 + 哈希桶结构,光对象头就占不少空间。
- 添加、删除、判断是否包含,全是位运算:
elements |= (1L 、<code>(elements & (1L - 求元素个数直接调
Long.bitCount(elements),不用遍历 - 没有装箱/拆箱开销(不像
HashSet<integer></integer>) - 没有哈希冲突,也不需要重写
hashCode()或equals()
创建和操作必须严格绑定枚举类型
EnumSet 只接受同一枚举类的实例,且类型在创建时就固化。这既是限制,也是性能来源——编译期就知道所有可能值,运行时能直接算出 bit 位偏移。
- 正确写法:
EnumSet.noneOf(Status.class)、EnumSet.of(Status.PENDING, Status.DONE) - 错误写法:
new EnumSet()(编译失败)、EnumSet.of((Enum)someObject)(类型不匹配) - 不能 add null,也不能传入非该枚举类型的值,否则立即抛
NullPointerException或ClassCastException
批量操作天然支持位级集合运算
交集、并集、补集这些操作,在 EnumSet 里不是循环比对,而是直接 long 与 long 的位运算,O(1) 完成。
-
enabled.retainAll(required)→ 对应elements &= required.elements -
EnumSet.union(setA, setB)→setA.elements | setB.elements -
set.complementOf(universe)→universe.elements ^ set.elements - 比手动遍历
addAll()或用 stream filter 快一个数量级以上
适用场景明确,别强行替代通用集合
它不是万能的 Set,而是为“有限、固定、编译期已知”的枚举集合量身定制的。适合做状态组合、权限开关、功能启用列表等。
- ✅ 推荐:订单可流转的状态集、用户拥有的权限位、配置项启用开关
- ❌ 不适合:运行时动态加载的枚举值、需自定义排序(它永远按声明顺序迭代)、跨枚举类型混用
- 注意 JSON 或数据库反序列化后转 enum 时,务必校验字符串合法性,避免
valueOf()抛异常导致集合构建失败


















