从字符串转换为具有大量值的 Java 枚举

2022-09-01 02:04:10

假设我有一个包含 100 个值的枚举。为简单起见,请举一个以下示例:

public enum code
{
    CODE_1("string1"),
    CODE_2("string2"),
    CODE_3("string3"),
    CODE_4("string4"),
    ...
}

我想创建一个公共方法,将具有已知格式(如“string1”,“string2”...)的字符串转换为适当的枚举值CODE_1,CODE_2...通常,这是通过循环访问所有值来完成的,如果找到匹配项,则返回该枚举值。(详细信息可以在此问题中找到。

但是,我担心的是所有值的循环。这可能是一个巨大的瓶颈吗?如果不是100个元素,而是1000个元素呢?

作为我自己的练习,我试图用静态映射来优化这个查找,这可以确保给定任何字符串的O(1)查找时间。我喜欢这个额外的噱头,但我只想在实际需要时将其包含在我的代码中。您对使用迭代方法与地图方法有什么想法和发现?

public enum Code
{
    ...
    //enum values
    ...


    //The string-to-Code map
    private static final Map<String,Code> CODE_MAP = populateMap();

    private static Map<String,Code> populateMap()
    {
        Map<String,Code> map = new HashMap<String,Code>();

        for(Code c : Code.values())
        {
            map.put(c.getCode(), c);
        }

        return map;
    }


    private String code;

    private Code(String code)
    {
        this.code = code;
    }

    public String getCode()
    {
        return this.code;
    }

    public Code convertFromString(String code)
    {
        //assume that the given string is actually a key value in the map

        return (Code) CODE_MAP.get(code);
    }
}

答案 1

你想要一个,但如何整齐地填充它?枚举不允许在初始化枚举实例之前初始化静态字段,但有一个简洁的小技巧,称为按需初始化持有者成语,它使使用此功能所需的静态初始化映射变得容易实现:Map<String, Code>

public enum Code {
    CODE_1("string1"),
    CODE_2("string2"),
    CODE_3("string3"),
    // etc
    ;

    private static class Holder {
        static Map<String, Code> CODE_MAP = new HashMap<>();
    }

    private final String code;

    private Code(String code) {
        this.code = code;
        Holder.CODE_MAP.put(code, this);
    }

    public String getCode() {
        return this.code;
    }

    public Code convertFromString(String code) {
        return Holder.CODE_MAP.get(code);
    }
}

这是可行的,因为类装入器在初始化枚举类之前初始化内部静态类,因此在枚举实例初始化期间分配映射以准备加载。

无循环。没有特殊代码来加载映射(在构造函数中完成)。最小代码。


答案 2

地图是不错的选择:更干净的代码和.如果你使用,那么你得到的最好的是O(1)for-loopO(n)