在Java的集合框架中,EnumMap是一种特殊的Map实现,它的键必须是同一种枚举类型的实例,内部通过数组存储数据,因此相比HashMap等通用Map实现,有着更快的访问速度和更低的内存开销,非常适合用于枚举键的键值对存储场景。

EnumMap的基本特性
EnumMap的所有键都必须是同一个枚举类型的实例,创建EnumMap时必须指定对应的枚举类型。它的迭代顺序是按照枚举常量在枚举类中声明的顺序来排列的,这一点和枚举的天然顺序一致。同时EnumMap是线程不安全的,如果需要多线程使用,需要额外做同步处理。
创建EnumMap
创建EnumMap有两种常用方式,一种是指定枚举类型创建空Map,另一种是通过已有的Map来初始化。首先我们先定义一个枚举类型作为示例:
// 定义示例枚举类型
public enum WeekDay {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}接下来是创建EnumMap的代码示例:
import java.util.EnumMap;
import java.util.HashMap;
import java.util.Map;
public class EnumMapDemo {
public static void main(String[] args) {
// 方式1:指定枚举类型创建空EnumMap
EnumMap<WeekDay, String> enumMap1 = new EnumMap<>(WeekDay.class);
// 方式2:通过已有Map初始化EnumMap
Map<WeekDay, String> tempMap = new HashMap<>();
tempMap.put(WeekDay.MONDAY, "上班");
tempMap.put(WeekDay.SATURDAY, "休息");
EnumMap<WeekDay, String> enumMap2 = new EnumMap<>(tempMap);
}
}EnumMap的增删改查操作
EnumMap的常用操作和普通Map基本一致,支持put添加键值对、get获取值、remove删除键值对、containsKey判断键是否存在等操作,下面是完整的操作示例:
import java.util.EnumMap;
import java.util.Map;
public class EnumMapOperation {
public static void main(String[] args) {
// 创建EnumMap并添加键值对
EnumMap<WeekDay, String> scheduleMap = new EnumMap<>(WeekDay.class);
scheduleMap.put(WeekDay.MONDAY, "开周会");
scheduleMap.put(WeekDay.TUESDAY, "写需求文档");
scheduleMap.put(WeekDay.WEDNESDAY, "开发功能模块");
// 获取指定键对应的值
String mondaySchedule = scheduleMap.get(WeekDay.MONDAY);
System.out.println("周一安排:" + mondaySchedule); // 输出:周一安排:开周会
// 修改已有键的值
scheduleMap.put(WeekDay.MONDAY, "修改周会时间到下午");
System.out.println("修改后的周一安排:" + scheduleMap.get(WeekDay.MONDAY)); // 输出:修改后的周一安排:修改周会时间到下午
// 判断键是否存在
boolean hasFriday = scheduleMap.containsKey(WeekDay.FRIDAY);
System.out.println("是否有周五的安排:" + hasFriday); // 输出:是否有周五的安排:false
// 删除指定键的键值对
scheduleMap.remove(WeekDay.TUESDAY);
System.out.println("删除周二后的周二安排:" + scheduleMap.get(WeekDay.TUESDAY)); // 输出:删除周二后的周二安排:null
// 遍历EnumMap
System.out.println("所有日程安排:");
for (Map.Entry<WeekDay, String> entry : scheduleMap.entrySet()) {
System.out.println(entry.getKey() + ":" + entry.getValue());
}
}
}EnumMap的使用场景和注意事项
EnumMap最适合的场景就是键为枚举类型的键值对存储,比如状态映射、配置映射、日程安排等场景,此时使用EnumMap比HashMap效率更高。使用时需要注意以下几点:
- EnumMap的键不能为null,插入null键会抛出NullPointerException,但是值可以为null。
- EnumMap是线程不安全的,多线程环境下如果需要并发访问,可以使用Collections.synchronizedMap方法包装,或者选择其他线程安全的Map实现。
- EnumMap的迭代顺序是固定的,按照枚举常量声明的顺序排列,不需要额外排序操作。
- 创建EnumMap时必须指定枚举类型,否则无法正确初始化内部的数组存储结构。
EnumMap和普通HashMap的对比
我们可以通过下面的表格直观看到两者的区别:
| 对比项 | EnumMap | HashMap |
|---|---|---|
| 键类型要求 | 必须是同一种枚举类型的实例 | 可以是任意对象类型 |
| 存储结构 | 基于数组实现 | 基于哈希表实现 |
| 访问性能 | 更高,接近数组访问速度 | 相对较低,受哈希冲突影响 |
| 内存占用 | 更低,没有额外的哈希表开销 | 更高,需要维护哈希表结构 |
| 迭代顺序 | 按枚举声明顺序排列 | 无序,或按哈希顺序(不保证稳定) |
综上,当你的键值对场景明确键是枚举类型时,优先选择EnumMap可以获得更好的性能和更低的资源消耗。