介绍java中枚举类通过key获取value的几种方式,分析优缺点
chou403
/ Enum
/ c:
/ u:
/ 8 min read
方法 1: 静态代码块 + Map(如 HashMap 或 EnumMap)
使用静态代码块在类加载时初始化一个 Map
,将枚举常量的 key
和 value
存储到 Map
中,之后通过 Map
可以快速查找枚举对应的 value
。
优缺点
-
优点:
- 查找效率高:查找操作的时间复杂度为 O(1),即使枚举常量很多,查找性能依然优秀。
- 内存使用合理:内存占用与枚举常量数量成正比,
EnumMap
比HashMap
占用的内存更少。 - 代码简洁、易维护:一旦初始化完成,查找代码很简单且具有良好的可读性。
-
缺点:
- 初始化时开销:使用静态代码块进行初始化会增加类加载时的开销,虽然这个开销通常很小,但对于枚举常量特别多时可能有影响。
- 额外内存开销:每个枚举常量在
Map
中都会存储一份数据,因此在枚举常量较少时会有额外的内存开销。
适用场景
- 频繁查找且枚举常量较多(例如几十个或更多)时,查找效率要求较高。
示例代码
import java.util.EnumMap;
public enum Status {
SUCCESS(200, "OK"),
ERROR(500, "Server Error"),
NOT_FOUND(404, "Not Found");
private final int code;
private final String message;
// 使用 EnumMap 存储枚举常量与其 message
private static final EnumMap<Status, String> MAP = new EnumMap<>(Status.class);
static {
// 初始化 Map
for (Status status : Status.values()) {
MAP.put(status, status.message);
}
}
Status(int code, String message) {
this.code = code;
this.message = message;
}
// 通过枚举获取 message
public static String getMessageByStatus(Status status) {
return MAP.get(status);
}
}
方法 2: 遍历 values()
每次查找时,通过遍历 values()
数组查找与给定 key
对应的枚举常量。
优缺点
-
优点:
- 实现简单:不需要额外的数据结构,直接通过
values()
数组遍历查找。 - 内存开销小:没有额外的
Map
或其他数据结构,因此内存使用最小。
- 实现简单:不需要额外的数据结构,直接通过
-
缺点:
- 查找效率较低:查找的时间复杂度是 O(n),对于大量枚举常量,查找性能较差。
- 不适合频繁查找:如果枚举常量较多,频繁查找时性能会显著下降。
适用场景
- 枚举常量较少(如 5 到 10 个枚举常量),查找频率不高时。
示例代码
public enum Status {
SUCCESS(200, "OK"),
ERROR(500, "Server Error"),
NOT_FOUND(404, "Not Found");
private final int code;
private final String message;
Status(int code, String message) {
this.code = code;
this.message = message;
}
// 通过 code 获取对应的枚举
public static Status getByCode(int code) {
// 遍历 values() 查找匹配的枚举
for (Status status : Status.values()) {
if (status.code == code) {
return status;
}
}
return null; // 如果没有找到
}
}
方法 3: switch / if-else
直接使用 switch
或 if-else
语句判断 key
,获取对应的 value
。对于少量枚举常量非常高效。
优缺点
-
优点:
- 性能最高:查找操作的时间复杂度为 O(1),查找速度非常快,尤其是在枚举常量较少时。
- 实现简单:无需额外的数据结构,直接通过条件判断进行匹配。
-
缺点:
- 代码不易维护:如果枚举常量较多,
switch
或if-else
语句会变得冗长,难以维护。 - 灵活性差:需要手动更新
switch
语句或if-else
,不适用于动态变化的枚举常量。
- 代码不易维护:如果枚举常量较多,
适用场景
- 枚举常量较少(如 5 个以内),且查找频繁的场景。
示例代码
public enum Status {
SUCCESS(200, "OK"),
ERROR(500, "Server Error"),
NOT_FOUND(404, "Not Found");
private final int code;
private final String message;
Status(int code, String message) {
this.code = code;
this.message = message;
}
// 通过 code 获取对应的枚举,使用 switch 语句
public static Status getByCode(int code) {
switch (code) {
case 200: return SUCCESS;
case 500: return ERROR;
case 404: return NOT_FOUND;
default: return null;
}
}
}
方法 4: ConcurrentHashMap(线程安全)
使用 ConcurrentHashMap
来存储 key
和 value
,适用于多线程环境中对枚举常量的并发访问。
优缺点
-
优点:
- 线程安全:适合多线程并发环境,确保线程安全。
- 查找高效:查找操作的时间复杂度为 O(1),和普通的
HashMap
相同。 - 高效并发访问:设计上支持高效的并发访问,避免了锁的开销。
-
缺点:
- 内存开销较高:相比普通的
HashMap
,ConcurrentHashMap
的内存开销更大。 - 不适用于单线程环境:如果不在并发环境中使用,它的优势无法体现,可能会增加不必要的开销。
- 内存开销较高:相比普通的
适用场景
- 多线程并发访问场景,确保线程安全。
示例代码
import java.util.concurrent.ConcurrentHashMap;
public enum Status {
SUCCESS(200, "OK"),
ERROR(500, "Server Error"),
NOT_FOUND(404, "Not Found");
private final int code;
private final String message;
// 使用 ConcurrentHashMap 存储
private static final ConcurrentHashMap<Integer, Status> MAP = new ConcurrentHashMap<>();
static {
// 初始化 Map
for (Status status : Status.values()) {
MAP.put(status.code, status);
}
}
Status(int code, String message) {
this.code = code;
this.message = message;
}
// 通过 code 获取对应的枚举
public static Status getByCode(int code) {
return MAP.get(code);
}
}
方法 5: EnumMap(专为枚举设计)
EnumMap
是 Map
的一种专为枚举设计的实现,它提供了比 HashMap
更优的性能。
优缺点
-
优点:
- 性能高:
EnumMap
为枚举常量的查找进行了优化,内存和性能方面都优于普通的HashMap
。 - 内存占用低:特别是在枚举常量较多时,
EnumMap
可以显著减少内存开销。
- 性能高:
-
缺点:
- 仅适用于枚举:
EnumMap
只适用于枚举类型,不能用于其他类型作为key
。 - 初始化稍复杂:需要在静态块或初始化时填充
EnumMap
。
- 仅适用于枚举:
适用场景
- 枚举常量较多,并且需要高效查找时。
示例代码
import java.util.EnumMap;
public enum Status {
SUCCESS(200, "OK"),
ERROR(500, "Server Error"),
NOT_FOUND(404, "Not Found");
private final int code;
private final String message;
// 使用 EnumMap 存储枚举常量与其对应的枚举
private static final EnumMap<Status, String> MAP = new EnumMap<>(Status.class);
static {
// 初始化 EnumMap
for (Status status : Status.values()) {
MAP.put(status, status.message);
}
}
Status(int code, String message) {
this.code = code;
this.message = message;
}
// 通过枚举获取 message
public static String getMessageByStatus(Status status) {
return MAP.get(status);
}
}
总结
方法 | 查找效率 | 内存使用 | 适用场景 |
---|---|---|---|
静态代码块 + Map | O(1) | 较高(取决于枚举数量) | 枚举常量较多,查找频繁 |
遍历 values() | O(n) | 低 | 枚举常量少,查找不频繁 |
switch / if-else | O(1) | 低 | 枚举常量少,查找频繁 |
ConcurrentHashMap | O(1) | 高 | 多线程并发访问,保证线程安全 |
EnumMap | O(1) | 优化(低内存) | 枚举常量较多,查找频繁且内存要求高 |
根据你的具体需求选择最合适的方法。