You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java如何通过十六进制颜色码字符串匹配获取对应自定义枚举值

核心原理

枚举内置的valueOf()方法仅支持通过枚举常量的定义名(即REDORANGE这类写在枚举类里的标识符)匹配实例,无法直接匹配自定义的十六进制色值属性,需要自行实现反向查找逻辑。
原有代码存在两处需要修正的问题:

  • 枚举常量之间必须用逗号分隔,最后一个常量末尾要加分号,否则编译不通过
  • ORANGE项配置的色值缺少#前缀,和入参格式不统一,会导致匹配失败
实现方案

最优做法是在枚举类内部维护一个静态查找映射表,类加载时就把所有枚举项和对应色值的映射关系缓存好,查找时直接从缓存取。

用静态Map缓存的原因是枚举的values()方法每次调用都会生成并返回一个新的枚举实例数组,如果每次查找都遍历全量枚举,高频调用场景下会产生不必要的内存和性能开销,类加载时一次性缓存映射关系可以实现O(1)时间复杂度的查找。

修正后的完整代码

import java.util.HashMap;
import java.util.Map;

public enum ColorList {
    RED("#FF0000"),
    ORANGE("#FFA500");

    private final String value;
    private static final Map<String, ColorList> HEX_TO_ENUM_MAP = new HashMap<>();

    static {
        for (ColorList color : values()) {
            HEX_TO_ENUM_MAP.put(color.value, color);
        }
    }

    ColorList(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }

    // 自定义反向查找方法
    public static ColorList getByHexCode(String hexColor) {
        if (hexColor == null) {
            throw new IllegalArgumentException("色值不能为空");
        }
        // 兼容不带#前缀的入参,自动补全格式
        String standardHex = hexColor.startsWith("#") ? hexColor : "#" + hexColor;
        ColorList res = HEX_TO_ENUM_MAP.get(standardHex.toUpperCase());
        if (res == null) {
            throw new IllegalArgumentException("不存在对应色值的枚举项:" + hexColor);
        }
        return res;
    }
}

public void handleColor(String hexColor) {
    // 替换原生valueOf,调用自定义查找方法
    ColorList myColor = ColorList.getByHexCode(hexColor);
    doWithColor(myColor);
}

public void doWithColor(ColorList myColor) {
    System.out.println(myColor.name());
    // 传入#FF0000时此处输出RED
    System.out.println(myColor.getValue());
    // 传入#FF0000时此处输出#FF0000
}

可选调整点

  • 如果需要兼容大小写不匹配的场景,可以在存入缓存和查找时统一把色值转为大写/小写
  • 如果业务允许不存在的色值走默认逻辑,可以把抛异常的逻辑改为返回默认枚举项(比如返回null或者新增的UNKNOWN颜色项)
  • 如果色值格式有统一规范,可以在查找方法里加正则校验,提前拦截格式非法的入参

内容的提问来源于stack exchange,提问作者user18837670

火山引擎 最新活动