Arm*_*and 72 java enums static-initializer
我在博客上看到它建议以下是使用getCode(int)Java枚举进行"反向查找"的合理方法:
public enum Status {
WAITING(0),
READY(1),
SKIPPED(-1),
COMPLETED(5);
private static final Map<Integer,Status> lookup
= new HashMap<Integer,Status>();
static {
for(Status s : EnumSet.allOf(Status.class))
lookup.put(s.getCode(), s);
}
private int code;
private Status(int code) {
this.code = code;
}
public int getCode() { return code; }
public static Status get(int code) {
return lookup.get(code);
}
}
Run Code Online (Sandbox Code Playgroud)
对我来说,静态地图和静态初始化程序看起来都是个坏主意,我的第一个想法就是将查询编码为:
public enum Status {
WAITING(0),
READY(1),
SKIPPED(-1),
COMPLETED(5);
private int code;
private Status(int code) {
this.code = code;
}
public int getCode() { return code; }
public static Status get(int code) {
for(Status s : values()) {
if(s.code == code) return s;
}
return null;
}
}
Run Code Online (Sandbox Code Playgroud)
这两种方法都有明显的问题,是否有推荐的方法来实现这种查找?
小智 25
来自Google的Guava的Maps.uniqueIndex非常适合构建查找地图.
更新:以下是使用Maps.uniqueIndexJava 8 的示例:
public enum MyEnum {
A(0), B(1), C(2);
private static final Map<Integer, MyEnum> LOOKUP = Maps.uniqueIndex(
Arrays.asList(MyEnum.values()),
MyEnum::getStatus
);
private final int status;
MyEnum(int status) {
this.status = status;
}
public int getStatus() {
return status;
}
@Nullable
public static MyEnum fromStatus(int status) {
return LOOKUP.get(status);
}
}
Run Code Online (Sandbox Code Playgroud)
Mat*_*all 20
虽然它具有更高的开销,但静态映射很好,因为它提供了恒定时间查找code.您的实现的查找时间随着枚举中的元素数量线性增加.对于小型枚举,这根本不会有显着贡献.
这两种实现的一个问题(并且,可以说,通常使用Java枚举)是一个隐藏的额外值,它Status可以承担:null.根据业务逻辑的规则Exception,当查找"失败"时,返回实际的枚举值或抛出一个值是有意义的.
这是一个可能更快的替代方案:
public enum Status {
WAITING(0),
READY(1),
SKIPPED(-1),
COMPLETED(5);
private int code;
private Status(int code) {
this.code = code;
}
public int getCode() { return code; }
public static Status get(int code) {
switch(code) {
case 0: return WAITING;
case 1: return READY;
case -1: return SKIPPED;
case 5: return COMPLETED;
}
return null;
}
}
Run Code Online (Sandbox Code Playgroud)
当然,如果您希望以后能够添加更多常量,那么这不是真正可维护的.