获取与 int 值关联的枚举

以前,我将 LegNo 枚举简单地定义为:

NO_LEG, LEG_ONE, LEG_TWO

通过调用 return LegNo.values()[i];,我能够得到与每个枚举相关联的值。

但是现在我决定将 LegNo枚举 NO_LEG设置为 int-1,而不是0 所以我决定使用一个私有构造函数来初始化并设置它的 int 值

NO_LEG(-1), LEG_ONE(1), LEG_TWO(2);


private LegNo(final int leg) { legNo = leg; }

现在唯一的问题是,因为我是这样做的,所以 values()方法对于 NO_LEG枚举不起作用。如何获得与 int 相关联的枚举?除了使用 case switch 语句或 if-elseif 外,还有其他有效的方法吗

我可以看到很多关于从枚举中获取 int 值的 SO 问题,但我想要的是相反的结果。

109004 次浏览

EDIT August 2018

Today I would implement this as follows

public enum LegNo {
NO_LEG(-1), LEG_ONE(1), LEG_TWO(2);


private final int value;


LegNo(int value) {
this.value = value;
}


public static Optional<LegNo> valueOf(int value) {
return Arrays.stream(values())
.filter(legNo -> legNo.value == value)
.findFirst();
}
}

You'll have to maintain a mapping inside the enum.

public enum LegNo {
NO_LEG(-1), LEG_ONE(1), LEG_TWO(2);


private int legNo;


private static Map<Integer, LegNo> map = new HashMap<Integer, LegNo>();


static {
for (LegNo legEnum : LegNo.values()) {
map.put(legEnum.legNo, legEnum);
}
}


private LegNo(final int leg) { legNo = leg; }


public static LegNo valueOf(int legNo) {
return map.get(legNo);
}
}

The static block will be invoked only once, so there is practically no performance issue here.

EDIT: Renamed the method to valueOf as it is more inline with other Java classes.

Since your enum only contains 3 elements, the fastest way will be to just use a series of if else, like you suggested.

edit: the answer that adarshr provided is better suited for general cases, where there are many enum values, but I think it is an overkill for your problem.

You could also include a static method in the enum that iterates through all members and returns the correct one.

public enum LegNo {
NO_LEG(-1),
LEG_ONE(1),
LEG_TWO(2);


private int legIndex;


private LegNo(int legIndex) { this.legIndex = legIndex; }


public static LegNo getLeg(int legIndex) {
for (LegNo l : LegNo.values()) {
if (l.legIndex == legIndex) return l;
}
throw new IllegalArgumentException("Leg not found. Amputated?");
}
}

Now, if you want to get an Enum value by the integer, you just use:

int myLegIndex = 1; //expected : LEG_ONE
LegNo myLeg = LegNo.getLeg(myLegIndex);
public enum LegNo {
NO_LEG(-1), LEG_ONE(1), LEG_TWO(2);


private int legNo;


private LegNo(int leg) { legNo = leg; }


public static LegNo valueOf(int legNo) {
for (LegNo leg : LegNo.values()) {
if (leg.legNo == legNo) return leg;
}
}
}


assert LegNo.valueOf(2) == LegNo.LEG_TWO
assert LegNo.valueOf(3) == null

adarshr's answer adapted to Java 8:

import static java.util.Arrays.stream;
import static java.util.stream.Collectors.toMap;


import java.util.Map;


public enum LegNo {
NO_LEG(-1), LEG_ONE(1), LEG_TWO(2);


private final int legNo;


private final static Map<Integer, LegNo> map =
stream(LegNo.values()).collect(toMap(leg -> leg.legNo, leg -> leg));


private LegNo(final int leg) {
legNo = leg;
}


public static LegNo valueOf(int legNo) {
return map.get(legNo);
}
}

You can also access Enum value corresponding to given integer value simply by calling values() method on enum LegNo. It returns field of LegNo enums: LegNo.values()[0]; //returns LEG_NO LegNo.values()[1]; //returns LEG_ONE LegNo.values()[2]; //returns LEG_TWO

Not precisely the thing he was looking for, but pretty close though and very simple indeed. (Although the subject is dead it might be useful for someone else.)

Java 8 way with default value:

public enum LegNo {
NO_LEG(-1), LEG_ONE(1), LEG_TWO(2);


private final int legNo;


LegNo(int legNo) {
this.legNo = legNo;
}


public static LegNo find(int legNo, Supplier<? extends LegNo> byDef) {
return Arrays.asList(LegNo.values()).stream()
.filter(e -> e.legNo == legNo).findFirst().orElseGet(byDef);
}
}

to call:

LegNo res = LegNo.find(0, () -> LegNo.NO_LEG);

or with Exception:

LegNo res = LegNo.find(0, () -> {
throw new RuntimeException("No found");
});
public enum LegNo {


NO_LEG(-1), LEG_ONE(1), LEG_TWO(2);


private final int code;


LegNo(int code) {
this.code = code;
ReverseStorage.reverseMap.put(code, this);
}


public static Optional<LegNo> getByCode(int code) {
return Optional.ofNullable(ReverseStorage.reverseMap.get(code));
}


private static final class ReverseStorage {
private static final Map<Integer, LegNo> reverseMap = new LinkedHashMap<>();
}
}