EnumSet 是 Java 中基于位向量实现的高性能枚举集合,所有操作均为常数时间位运算,比 HashSet 更快、比 TreeSet 更省内存;必须通过静态工厂方法创建,支持 allOf、noneOf、of、range 等高效初始化方式,适用于状态管理、权限控制与批量过滤等场景。

EnumSet 是 Java 中专为枚举类型设计的高性能集合,它不靠哈希或树结构,而是用位向量(bit vector)直接映射每个枚举常量到一个二进制位。这意味着存储和操作几乎全是位运算,没有装箱、不触发扩容、不产生额外对象——所以它比 HashSet 快得多,也比 TreeSet 更省内存。
创建方式决定效率起点
EnumSet 没有 public 构造器,必须用静态工厂方法创建。选对方法能避免无效循环或冗余判断:
- allOf(Class<E>):一次性填满所有枚举值,底层直接设高位,比循环 add 所有值快一个数量级
- noneOf(Class<E>):返回空集合,开销极小,适合后续按条件动态添加
-
of(E...):支持最多 5 个参数重载,适合固定少量值;超过时可用
of(e1, e2).addAll(EnumSet.of(e3, e4, e5)) -
range(E from, E to):仅当枚举定义顺序连续时安全(如
Day.MONDAY到Day.FRIDAY),内部按 ordinal 线性截取,跳过中间缺失值会出错
操作全在常数时间完成
所有基本操作都基于位运算,不受集合大小影响:
-
add(e)和remove(e):根据枚举的ordinal()定位对应 bit,执行 or 或 xor -
contains(e):检查指定位置是否为 1,比 HashMap 的 hash 查找更快更稳定 -
retainAll(s)和removeAll(s):本质是两个 long 值的 & 或 &~ 运算,一次到位 -
clear():直接清空底层 long 数组,比新建一个 noneOf 实例更轻量
注意边界和适用场景
高效的前提是守规矩:
立即学习“Java免费学习笔记(深入)”;
- 只能存一种已知枚举类型,不能混装,也不能存 null(add null 会抛 NullPointerException)
- 非线程安全,多线程写入需外层同步,不要指望它自己加锁
- 序列化后反序列化要求目标环境枚举类存在且常量顺序未变,增删中间值会导致数据错位
- 遍历顺序永远是枚举声明顺序,不是插入顺序,也不支持自定义排序
典型实用模式
把 EnumSet 当作状态开关或权限标记来用,效果最明显:
- 状态机管理:比如
EnumSet<OrderStatus> pendingStates = EnumSet.of(PENDING, PROCESSING);,校验当前状态是否合法 - 权限组合:用
EnumSet<Permission> userPerms = EnumSet.noneOf(Permission.class);动态累加权限 - 批量过滤:
availableTypes.retainAll(supportedTypes)快速求交集,比流式 filter + contains 高效得多 - 缓存常用实例:如
public static final EnumSet<Day> WEEKDAYS = EnumSet.range(MONDAY, FRIDAY);,避免重复创建


















