Home
img of docs

介绍java中枚举类通过key获取value的几种方式,分析优缺点

chou403

/ Enum

/ c:

/ u:

/ 8 min read


方法 1: 静态代码块 + Map(如 HashMap 或 EnumMap)

使用静态代码块在类加载时初始化一个 Map,将枚举常量的 keyvalue 存储到 Map 中,之后通过 Map 可以快速查找枚举对应的 value

优缺点

  • 优点:

    • 查找效率高:查找操作的时间复杂度为 O(1),即使枚举常量很多,查找性能依然优秀。
    • 内存使用合理:内存占用与枚举常量数量成正比,EnumMapHashMap 占用的内存更少。
    • 代码简洁、易维护:一旦初始化完成,查找代码很简单且具有良好的可读性。
  • 缺点:

    • 初始化时开销:使用静态代码块进行初始化会增加类加载时的开销,虽然这个开销通常很小,但对于枚举常量特别多时可能有影响。
    • 额外内存开销:每个枚举常量在 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

直接使用 switchif-else 语句判断 key,获取对应的 value。对于少量枚举常量非常高效。

优缺点

  • 优点:

    • 性能最高:查找操作的时间复杂度为 O(1),查找速度非常快,尤其是在枚举常量较少时。
    • 实现简单:无需额外的数据结构,直接通过条件判断进行匹配。
  • 缺点:

    • 代码不易维护:如果枚举常量较多,switchif-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 来存储 keyvalue,适用于多线程环境中对枚举常量的并发访问。

优缺点

  • 优点:

    • 线程安全:适合多线程并发环境,确保线程安全。
    • 查找高效:查找操作的时间复杂度为 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(专为枚举设计)

EnumMapMap 的一种专为枚举设计的实现,它提供了比 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);
    }
}

总结

方法查找效率内存使用适用场景
静态代码块 + MapO(1)较高(取决于枚举数量)枚举常量较多,查找频繁
遍历 values()O(n)枚举常量少,查找不频繁
switch / if-elseO(1)枚举常量少,查找频繁
ConcurrentHashMapO(1)多线程并发访问,保证线程安全
EnumMapO(1)优化(低内存)枚举常量较多,查找频繁且内存要求高

根据你的具体需求选择最合适的方法。