从String转换为具有大量值的Java枚举 [英] Convert from String to a Java enum with large amount of values

查看:466
本文介绍了从String转换为具有大量值的Java枚举的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  public枚举代码
{
CODE_1(string1 ),
CODE_2(string2),
CODE_3(string3),
CODE_4(string4),
...
}

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



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



作为一个练习,我试图用静态映射优化这个查找,这可以保证O(1)查找时间给定任何字符串。我喜欢这个额外的g头,但是如果实际上是必要的,我只想将其包含在我的代码中。你使用迭代方法vs map方法的想法和发现是什么?

  public enum Code 
{
...
//枚举值
...


//字符串代码映射
private static final Map<串,代码和GT; CODE_MAP = populateMap();

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

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

返回地图;
}


私人字符串代码;

私人代码(String code)
{
this.code = code;
}

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

public代码convertFromString(String code)
{
//假定给定的字符串实际上是地图中的键值

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


解决方案

你想要一个 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;

私人代码(String code){
this.code = code;
Holder.CODE_MAP.put(code,this);
}

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

public代码convertFromString(String code){
return CODE_MAP.get(code);
}
}

这是因为类加载器初始化内部静态类 before 初始化枚举类,所以在枚举实例初始化期间,映射被分配准备加载。



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


Let's say I have an enum with 100 values. For simplicity's sake, take the following example:

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

I want to create a public method to convert strings with a known format (like "string1", "string2"...) to the appropiate enum value CODE_1, CODE_2... Typically this is done by iterating over all values, and if a match is found, return that enum value. (Details can be found in this question.)

However, I'm concerned with reguraly looping over all values. Could this potentially be a huge bottleneck? What if instead of 100 element, there were 1000?

As an exercise for myself, I tried to optimize this lookup with a static map, which can assure O(1) lookup time given any string. I like this extra gimmick, but I only want to include it in my code if it is actually necessary. What are your thoughts and findings on using the iterating method vs the map method?

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);
    }
}

解决方案

You want a Map<String, Code>, but how to populate it neatly? Enums don't allow you to initialize a static fields before the enum instances are initialized, but there's a neat little trick, called the Initialization-on-demand holder idiom, that makes using a statically initialized map needed for this functionality easy to implement:

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 CODE_MAP.get(code);
    }
}

This works because the class loader initializes inner static classes before initializing the enum class, so the map is assigned ready to load during enum instance initialization.

No loops. No special code to load the map (done in constructor). Minimal code.

这篇关于从String转换为具有大量值的Java枚举的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆