如何改进这种枚举类型?
我会经常需要从串码转换成其Enum
类型。 请参阅下面的代码片段。我认为这是非常低效的。如何改进 方法deref
以便:如何改进这种枚举类型?
- 这将是线程安全的。
- 这是更快。
代码:
public enum SigninErrorCodes
{
InvalidUser("a0"), InvalidPassword("b5"), NoServerResponse("s2");
SigninErrorCodes(String code) { _code = code; }
public String code() { return _code; }
public static SigninErrorCodes deref(String code)
{
SigninErrorCodes[] verbs = values();
Map<String, SigninErrorCodes> m = new HashMap<String,SigninErrorCodes>(3);
for(int i=0; i<verbs.length; i++)
m.put(verbs[i].code(), verbs[i]);
return m.get(code);
}
private final String _code;
}
如果可能的值的列表真的就是这么小,然后手工编写的方法。与单纯的3个字符串比较相比,哈希表的性能优势不会受到影响。
但是,如果像我怀疑,值的数量要大于你写了那么一个地图是有道理的,在这种情况下创建枚举时,你应该缓存地图。
public enum SigninErrorCodes {
InvalidUser("a0"), InvalidPassword("b5"), NoServerResponse("s2");
private final String _code;
SigninErrorCodes(String code) { _code = code; }
public String code() { return _code; }
private static final Map<String, SigninErrorCodes> m;
static {
SigninErrorCodes[] verbs = values();
m = new HashMap<String,SigninErrorCodes>(verbs.length * 2);
for(int i=0; i<verbs.length; i++)
m.put(verbs[i].code(), verbs[i]);
}
public static SigninErrorCodes deref(String code) {
return m.get(code);
}
}
请注意,给出散列图的最佳大小不是元素的数量,而是大约两倍。较低的数字会导致关键冲突。
枚举有一个称为[的valueOf] [1]来处理这个静态方法。你会这样做:
public static SigninErrorCodes deref(String code){
try {
return Enum.valueOf(SignInErrorCodes.class, code);
} catch (IllegalArgumentException e) {
return null;
} catch (NullPointerException e) {
return null;
}
}
请注意,这里的错误处理尝试模仿与原始方法相同的结果。这可能不是事实,你希望如何处理无效代码,或者你可能会假设会有在运行时不存在无效代码,那么你只会让例外传播。
上述适用,如果你可以根据代码命名枚举(东西都是非常需要在这种情况下,它似乎)。
如果由于某种原因无法实现,那么您可以很简单地使用Hashtable(同步化)作为您的映射实现,并将其保存在静态字段中,并将其填充到枚举的构造函数中。把(_code,this.getClass());)。
如果过度同步化太多的性能,明智的,然后再看看存储一个ThreadLocal地图。
[1]:http://java.sun.com/javase/6/docs/api/java/lang/Enum.html#valueOf(java.lang.Class,java.lang.String中)
您也可以只调用的valueOf静态成员:SigninErrorCodes.valueOf(代码);但是,根据计划,每个未接电话的例外成本可能很高。 – 2009-06-29 03:05:16
一两件事,这将使它更快保持地图在一个静态变量,这样你就不必每次重新计算它;不知道线程安全的部分。
public enum SigninErrorCodes {
InvalidUser("a0"), InvalidPassword("b5"), NoServerResponse("s2");
private static Map<String, SigninErrorCodes> m = new HashMap<String,SigninErrorCodes>(3);
SigninErrorCodes(String code) { _code = code; m.put(code, this); }
public String code() { return _code; }
public static SigninErrorCodes deref(String code)
{
return m.get(code);
}
}
如果代码串是有效的标识符,你可以使用它们作为枚举值直接:
public enum SigninErrorCodes { a0, b5, s2; }
// and then when you need to look it up, use:
SigninErrorCodes.valueOf("b5");
马库斯,这很有趣。你能否指出我的一个消息来源说HashMaps应该被初始化为其预期密钥的两倍? – Yishai 2009-06-29 03:07:24