Convert from String to a Java enum with large amount of values
假设我有一个具有100个值的枚举。为了简单起见,请使用以下示例:
1 2 3 4 5 6 7 8 | public enum code { CODE_1("string1"), CODE_2("string2"), CODE_3("string3"), CODE_4("string4"), ... } |
我想创建一个公共方法来将具有已知格式(如"string1"、"string2"…)的字符串转换为适当的枚举值代码_1、代码_2…通常,这是通过对所有值进行迭代来完成的,如果找到匹配项,则返回该枚举值。(在这个问题中可以找到详细信息。)
然而,我关注的是所有价值观的规范循环。这可能是一个巨大的瓶颈吗?如果不是100个元素,而是1000个呢?
作为我自己的一个练习,我尝试使用静态映射来优化这个查找,这可以确保给定任何字符串的O(1)查找时间。我喜欢这个额外的花招,但我只想在我的代码中包含它,如果真的有必要的话。您对使用迭代方法和映射方法有什么想法和发现?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | 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 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | 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); } } |
这是因为类加载器在初始化枚举类之前初始化内部静态类,所以在枚举实例初始化期间,映射被分配为随时可以加载。
没有循环。没有用于加载映射的特殊代码(在构造函数中完成)。最小代码。
如果字符串代码值是已知且一致的格式,则可以避免使用映射及其消耗的内存,并动态构造代码枚举查找值:
1 2 3 | public static Code convertFromString(String code) { return valueOf("CODE_" + code.substring("string".length())); } |
您提供的解决方案是正确的实现。
因为您只需要公开一个方法,而且它更具可读性。
使用
正如你提到的,复杂性是
地图是很好的选择:更清晰的代码和
好吧,映射解决方案的替代方案是一个巨大的switch语句(可以自动生成)或二进制搜索包含字符串的数组。我认为两者都不会在很大程度上超过HashMap的性能,尽管如果这真的很重要,那么通过基准测试您可能是最好的选择。
还有一件事没有被提到,那就是如果字符串具有某个枚举成员的确切名称,那么让我们将它转换为枚举值。如果这在您的案例中是完全可能的(只看您的示例,我看不到code.code_1如何不容易重命名code.string1等),我建议使用它,因为它根本不需要额外的编码,因此是最容易理解的。