EnumMap 底层使用固定长度的 Object[] 数组,容量等于枚举常量总数,键位置由 ordinal() 直接决定,操作为纯数组读写;构造必须传入枚举类字面量,不支持泛型推断;性能远超 HashMap,但要求键为具体 final 枚举且声明顺序不可变。

EnumMap 的数组存储不是“模拟”,而是真数组
EnumMap 底层是一个固定长度的 Object[],长度等于枚举类中常量总数(MyEnum.values().length)。它不借用哈希表逻辑,也不做任何桶管理或链表跳转。每个键的位置由其 ordinal() 值直接决定:声明顺序第一位是 0,第二位是 1,依此类推。put 或 get 操作就是一次整数计算加一次数组读写,没有分支判断、没有虚方法调用、不触发对象分配。
初始化必须传入枚举类字面量
EnumMap 无法靠泛型推断类型,构造时必须显式传入 MyEnum.class:
- ✅ 正确:
new EnumMap<OrderStatus, String>(OrderStatus.class) - ❌ 错误:
new EnumMap<>()(编译失败)或传错类(如String.class、Enum.class)会直接报错
这个 Class 对象不仅是类型标识,更是构建底层数组容量的唯一依据——JVM 用它查出所有枚举常量,一次性分配好数组空间。
键值操作完全绕过哈希与比较
HashMap 查一个 key 要经历:算 hash → 定位桶 → 遍历链表/红黑树 → 调 equals() 比较;EnumMap 全部跳过:
立即学习“Java免费学习笔记(深入)”;
- put(OrderStatus.PENDING, "routeA") → 写入
table[0](假设 PENDING.ordinal() == 0) - get(OrderStatus.FILLED) → 直接读取
table[3](假设 FILLED.ordinal() == 3) - 不涉及装箱、无扩容逻辑、无冲突处理、无 hashcode 计算
实测在高频交易场景中,get 吞吐量可达 HashMap 的 2–5 倍,GC 压力显著下降。
语义约束决定适用边界
高性能来自强约束,用之前必须确认三点:
- 键字段必须建模为具体、final、不可变的枚举类(不能是接口、抽象类或 int 常量)
- 全链路所有 put/get 必须使用同一枚举类实例(混用其他枚举会抛
IllegalArgumentException) - 枚举常量声明顺序上线后禁止调整(否则破坏跨服务序列化兼容性)
它不支持 null 键(调用即抛 NullPointerException),value 可为 null,但建议用 containsKey() 判断存在性,而非依赖 get() == null。



















