Java enum reverse look-up best practice

Armand picture Armand · Mar 15, 2011 · Viewed 44.6k times · Source

I saw it suggested on a blog that the following was a reasonable way to do a "reverse-lookup" using the getCode(int) in a Java enum:

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

To me, the static map and the static initializer both look like a bad idea, and my first thought would be to code the lookup as so:

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

Are there any obvious problems with either method, and is there a recommended way to implement this kind of lookup?

Answer

user638455 picture user638455 · Mar 15, 2011

Maps.uniqueIndex from Google's Guava is quite handy for building lookup maps.

Update: Here is an example using Maps.uniqueIndex with Java 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);
    }
}