2009-06-29 66 views
0

我会经常需要从串码转换成其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; 
} 

回答

1

如果可能的值的列表真的就是这么小,然后手工编写的方法。与单纯的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); 
    } 
} 

请注意,给出散列图的最佳大小不是元素的数量,而是大约两倍。较低的数字会导致关键冲突。

+0

马库斯,这很有趣。你能否指出我的一个消息来源说HashMaps应该被初始化为其预期密钥的两倍? – Yishai 2009-06-29 03:07:24

2

枚举有一个称为[的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中)

+1

您也可以只调用的valueOf静态成员:SigninErrorCodes.valueOf(代码);但是,根据计划,每个未接电话的例外成本可能很高。 – 2009-06-29 03:05:16

1

一两件事,这将使它更快保持地图在一个静态变量,这样你就不必每次重新计算它;不知道线程安全的部分。

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