EnumMap构造必须传入枚举类Class对象,不支持泛型推断;键不可为null,值可为null;迭代顺序固定为枚举声明顺序;内存比HashMap小20%~30%;非线程安全。

EnumMap 的构造必须传入枚举类,不能只传实例
Java 中 EnumMap 不是普通泛型 Map,它内部依赖枚举类的 values() 方法构建底层数组,所以构造时必须显式传入 Class<e></e>。传 null 或错类型会直接抛 NullPointerException 或 IllegalArgumentException。
常见错误是误以为像 HashMap 那样靠泛型推断——比如写 new EnumMap<Status, String>() 会编译失败,因为缺少运行时类信息。
- ✅ 正确写法:
new EnumMap<Status, String>(Status.class) - ❌ 错误写法:
new EnumMap<Status, String>()(编译不过) - ❌ 错误写法:
new EnumMap<Status, String>(someStatusInstance.getClass())(可能不是枚举类,且不安全)
EnumMap 不接受 null 键,但值可以为 null
和 EnumMap 的设计目标一致:它假设键空间固定、已知且非空。一旦你用 put(null, "x"),会立即触发 NullPointerException,连日志都来不及打。
这个限制其实帮你提前暴露逻辑错误——如果你的业务里“某个状态还没确定”,不该用 null 表示,而应定义一个 UNKNOWN 枚举常量。
立即学习“Java免费学习笔记(深入)”;
- ✅ 安全操作:
map.put(Status.ACTIVE, null)(值为 null 允许) - ❌ 危险操作:
map.put(null, "pending")(抛NullPointerException) - ⚠️ 注意:
get(null)同样抛异常,不是返回null
EnumMap 的迭代顺序永远是枚举声明顺序
不需要额外排序,也不受插入顺序影响。它的底层是数组,索引直接对应 enum.ordinal(),所以 keySet()、entrySet()、values() 全部按源码中枚举常量出现顺序返回。
这点在配置驱动、状态流转、UI 选项渲染等场景特别有用——你改枚举顺序,输出就自动对齐,不用再维护额外的排序逻辑。
- 例如:
enum Priority { LOW, MEDIUM, HIGH }→ 迭代永远是 LOW → MEDIUM → HIGH - 如果误把
HIGH写在最前,所有依赖顺序的逻辑都会悄悄错位 - ⚠️ 注意:
EnumMap没有sortedKeySet(),别想用它替代TreeMap
比 HashMap 小 20%~30% 内存,但只适用于枚举键
EnumMap 底层是 Object[],长度等于枚举常量个数;HashMap 则要维护 Node 数组 + 链表/红黑树节点对象。实测 10 个枚举常量时,EnumMap 实例内存占用约 64 字节,HashMap 约 96 字节(JDK 17 HotSpot)。
但这优势只在「键类型确定是枚举」且「枚举常量不多」时成立。一旦你试图用反射或字符串动态构造键,就该换回 HashMap 或 ConcurrentHashMap。
- ✅ 推荐场景:HTTP 状态码映射、订单状态文案、权限类型缓存
- ❌ 强行套用:把
String解析成枚举再塞进去——解析开销可能抵消内存优势 - ⚠️ 注意:
EnumMap不是线程安全的,多线程写入仍需外部同步
EnumMap。










