EnumSet用位向量实现,因枚举常量数量有限且序号唯一连续,支持O(1)位运算操作;RegularEnumSet用单个long(≤64个元素),JumboEnumSet用long[](超64个),按ordinal值定位比特位。

EnumSet内部用一个long或int类型的位向量(bit vector)来表示枚举常量的集合,每个枚举值对应一个固定位置的比特位。这种设计让添加、删除、判断是否包含等操作都变成单次位运算,时间复杂度稳定为O(1),且内存占用极小。
为什么用位向量而不是数组或哈希表
枚举类型在编译期就确定了所有可能的常量,且数量有限(最多64个时用long,更多则自动切换为long数组)。这使得每个枚举值可被赋予唯一、连续的序号(ordinal()),天然适配位索引。相比HashMap需计算hash、处理冲突、额外对象开销,位向量直接映射,无装箱、无指针、无扩容,空间局部性好,CPU缓存友好。
底层存储结构如何工作
EnumSet有两个具体实现类:RegularEnumSet(元素数≤64)和JumboEnumSet(更多)。前者只用一个long字段;后者用long[],每项管64个位。每个枚举常量的ordinal值决定它落在哪一位:比如E0.ordinal()==0 → 第0位,E1.ordinal()==1 → 第1位。插入E2就是对第2位执行 bits |= (1L ;判断是否含E2就是 (bits & (1L 。
集合运算如何靠位运算实现
并集、交集、差集全部转为对应位运算:
- 并集(union)→ 按位或(|):result.bits = set1.bits | set2.bits
- 交集(retainAll)→ 按位与(&):result.bits = set1.bits & set2.bits
- 差集(removeAll)→ 按位与非(& ~):result.bits = set1.bits & ~set2.bits
使用时需要注意的边界细节
EnumSet是抽象类,不能直接new,必须通过静态工厂方法创建,如EnumSet.of(E1, E2)或EnumSet.allOf(MyEnum.class)。它不支持null元素,也不允许混入非声明枚举类型的实例。另外,由于底层无顺序概念,遍历顺序由枚举常量声明顺序决定(即ordinal升序),不是插入顺序。

















