#1 楼
尝试MyEnum.values()[x]
,其中x
必须是0
或1
,即该枚举的有效序数。 请注意,在Java中,枚举实际上是类(并且枚举值因此是对象),因此您无法将
int
甚至Integer
转换为枚举。评论
+1:您可能希望将MyEnum.values()缓存为昂贵的缓存。也就是说,如果您拨打数百次。
– Peter Lawrey
2011年5月4日7:27
@PeterLawrey为了完整起见,您能解释一下为什么它应该很慢吗?我认为没有明显的原因。
–塔拉施
2012年12月4日,0:10
@Tarrasch因为数组是可变的,所以values()必须返回元素数组的副本,以防万一您更改它。每次创建此副本都是相对昂贵的。
– Peter Lawrey
2012年12月4日在8:44
@PeterLawrey我最近已经习惯了很多haskell(一切都是不可变的)!感谢您简洁明了的解释。 :)
–塔拉施
2012年12月4日17:46
如何获得“ x”?
– Beek Jk
17-10-5在4:41
#2 楼
MyEnum.values()[x]
是昂贵的操作。如果需要考虑性能,则可能需要执行以下操作:public enum MyEnum {
EnumValue1,
EnumValue2;
public static MyEnum fromInteger(int x) {
switch(x) {
case 0:
return EnumValue1;
case 1:
return EnumValue2;
}
return null;
}
}
评论
如果要避免进行开关维护,请在using类上:private final MyEnum [] myEnumValues = MyEnum.values();然后的用法:myEnum = myEnumValues [i];
– Gili Nachum
2012年6月4日18:20
@GiliNachum说的很奇怪,但是这个解决方案的问题是可维护性。它违反了DRY原理,这意味着每当枚举值发生更改(重新排序,添加值,删除值)时,switch语句都必须同时更新。 Gili的评论迫使Java保持与枚举值列表的一致性,对枚举值的更改完全不会影响该方法。
–丹德里·艾莉森(Dandre Allison)
13年1月8日在22:39
@LorenzoPolidori,您能解释一下为什么您将MyEnum.values()[x]视为昂贵的操作。我不知道它是如何工作的,但是对我来说,访问数组中的元素似乎没什么大不了的,也就是恒定的时间。如果必须构建阵列,则需要O(n)时间,这与您的解决方案的运行时间相同。
– Brunsgaard
13-10-4在18:06
@brunsgaard我假设每次值()都会生成一个新数组,因为数组是可变的,因此多次返回相同的数组并不安全。 switch语句不一定是O(n),它们可以编译为跳转表。因此,洛伦佐的主张似乎是合理的。
– MikeFHay
2014年1月24日在16:41
@Johnson Gili的版本不需要在Enum声明中进行任何更改即可。如果将新项目添加到枚举,则myEnum = myEnumValues [i]仍将返回枚举中的第i个项目,而无需进行任何更改。
–丹德里·艾莉森(Dandre Allison)
20 Feb 10'在2:08
#3 楼
如果要给出整数值,则可以使用以下结构public enum A
{
B(0),
C(10),
None(11);
int id;
private A(int i){id = i;}
public int GetID(){return id;}
public boolean IsEmpty(){return this.equals(A.None);}
public boolean Compare(int i){return id == i;}
public static A GetValue(int _id)
{
A[] As = A.values();
for(int i = 0; i < As.length; i++)
{
if(As[i].Compare(_id))
return As[i];
}
return A.None;
}
}
评论
+1是因为它强调了一个事实,即值不必是连续的。
–rhavin
13年2月6日在17:00
此外,如果您想要稀疏(或重复)的整数值集,而不是使用0 ..(count-1)的默认序数,则这似乎是唯一可行的答案。如果您要与现有代码交互(例如通过网络),那可能很重要。
– Benkc
13年4月22日在22:51
值得指出的是,如上述答案所示,缓存values()的结果可能是值得的,这样可以避免每次调用时分配内存和进行数组复制。
– Benkc
13年4月22日在22:52
并且,根据枚举的长度,您可能想要创建一个HashMap或使用二进制搜索或其他方式进行此查找,而不是每次都执行线性搜索。
– Benkc
13年4月22日在22:57
这应该是将int转换为枚举的正确方法和最佳实践,我认为您可以通过公共静态A GetValue(int _id){for(A a:A.values(){if(a.getId( )== _ id){return a;}}返回null;}摆脱None,isEmpty()和compare()的东西。
–邹Chris
2014年5月13日,3:15
#4 楼
您可以尝试这样。使用元素ID创建类。
public Enum MyEnum {
THIS(5),
THAT(16),
THE_OTHER(35);
private int id; // Could be other data type besides int
private MyEnum(int id) {
this.id = id;
}
public static MyEnum fromId(int id) {
for (MyEnum type : values()) {
if (type.getId() == id) {
return type;
}
}
return null;
}
}
现在使用id作为整数获取此枚举。
MyEnum myEnum = MyEnum.fromId(5);
#5 楼
我缓存值并创建一个简单的静态访问方法:public static enum EnumAttributeType {
ENUM_1,
ENUM_2;
private static EnumAttributeType[] values = null;
public static EnumAttributeType fromInt(int i) {
if(EnumAttributeType.values == null) {
EnumAttributeType.values = EnumAttributeType.values();
}
return EnumAttributeType.values[i];
}
}
评论
这是我现在使用的解决方案。但是恕我直言,如果您不为字段值提供与方法values()相同的名称,那么混乱就更少了。我使用cachedValues作为字段名。
–ToolmakerSteve
2015年6月27日,1:15
高效典雅;复制并粘贴到我的项目中:)我唯一更改的是fromInt(int i),我将其简称为from(int i),因为在签名中具有两次int有点多余。
– Pipedreambomb
17年5月18日在16:05
为什么不从头开始初始化?为什么要等待第一击?
– kaiser
18-2-15在23:41
#6 楼
Java枚举没有在C ++中进行的那种枚举到整数的映射。 br />MyEnum enumValue = MyEnum.values()[x];
应该可以工作。有点讨厌,如果可能,最好不要尝试从
values
s转换为int
s(反之亦然)。#7 楼
这不是通常要做的事情,所以我会重新考虑。但话虽如此,基本操作是:int->使用EnumType.values()[intNum]进行枚举,以及enum->使用enumInst.ordinal()进行int编程。values()的实现别无选择,只能给您一个数组的副本(java数组绝不是只读的),最好使用EnumMap来缓存枚举-> int映射。
评论
关于“这不是通常要做的事情”:有用的常见情况:枚举对应于存储在数据库中的int值。
–ToolmakerSteve
15年6月27日在1:09
@ToolmakerSteve,您对映射是绝对正确的。但是,您是否想将这种编码留给某些O-R映射器或某些工具箱/库?
– Dilum Ranatunga
15年8月19日在7:26
#8 楼
使用MyEnum enumValue = MyEnum.values()[x];
#9 楼
这是我计划使用的解决方案。这不仅适用于非顺序整数,而且还应与您可能希望用作枚举值的基础ID的任何其他数据类型一起使用。>我只需要在特定时间(从文件中加载数据时)将id转换为枚举,因此没有理由让我始终将Map保留在内存中。如果确实需要始终可访问地图,则可以始终将其作为Enum类的静态成员进行缓存。
评论
恕我直言,如果我担心内存使用情况,我将动态创建HashMap-类似于@ossys,但是当缓存为null时使用不同的代码,然后在使用完后添加第二个方法clearCachedValues(将私有字段设置回null) 。我认为MyEnum.fromInt(i)比传递地图对象更容易理解。
–ToolmakerSteve
2015年6月27日在1:23
#10 楼
如果它对其他人有帮助,我更喜欢的选项(此处未列出)使用Guava的Maps功能:或您的
null
可以返回throw IllegalArgumentException
,无论您喜欢哪种行为。评论
您应该提到您正在使用番石榴。或者您可以使用流:Map
– shmosel
17年11月16日0:53
可能还想定义一个getValue()方法。
– shmosel
17年11月16日在0:55
@shmosel糟糕,我错过了getValue函数,谢谢。将通用版本输入stackoverflow并不总是会成功。添加了有关通过链接使用番石榴的评论。首选番石榴方法而不是流方法。
–乍得·贝弗斯(Chad Befus)
17年11月16日在1:15
#11 楼
您可以遍历enum的values()
并将enum的整数值与给定的id
进行比较,如下所示:public enum TestEnum {
None(0),
Value1(1),
Value2(2),
Value3(3),
Value4(4),
Value5(5);
private final int value;
private TestEnum(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public static TestEnum getEnum(int value){
for (TestEnum e:TestEnum.values()) {
if(e.getValue() == value)
return e;
}
return TestEnum.None;//For values out of enum scope
}
}
并像这样使用:
TestEnum x = TestEnum.getEnum(4);//Will return TestEnum.Value4
我希望这样帮助;)
#12 楼
基于@ChadBefus的答案和@shmosel注释,我建议您使用它。 (高效查找,并且可以在纯Java> = 8上运行)import java.util.stream.Collectors;
import java.util.function.Function;
import java.util.Map;
import java.util.Arrays;
public enum MyEnum {
OPTION_1(-66),
OPTION_2(32);
private int value;
private MyEnum(final int value) {
this.value = value;
}
public int getValue() {
return this.value;
}
private static Map<Integer, MyEnum> reverseLookup =
Arrays.stream(MyEnum.values()).collect(Collectors.toMap(MyEnum::getValue, Function.identity()));
public static MyEnum fromInt(final int id) {
return reverseLookup.getOrDefault(id, OPTION_1);
}
public static void main(String[] args) {
System.out.println(fromInt(-66).toString());
}
}
#13 楼
编写了此实现。它允许缺失值,负值并保持代码一致。该地图也被缓存。使用接口并需要Java8。枚举
public enum Command implements OrdinalEnum{
PRINT_FOO(-7),
PRINT_BAR(6),
PRINT_BAZ(4);
private int val;
private Command(int val){
this.val = val;
}
public int getVal(){
return val;
}
private static Map<Integer, Command> map = OrdinalEnum.getValues(Command.class);
public static Command from(int i){
return map.get(i);
}
}
接口
public interface OrdinalEnum{
public int getVal();
@SuppressWarnings("unchecked")
static <E extends Enum<E>> Map<Integer, E> getValues(Class<E> clzz){
Map<Integer, E> m = new HashMap<>();
for(Enum<E> e : EnumSet.allOf(clzz))
m.put(((OrdinalEnum)e).getVal(), (E)e);
return m;
}
}
#14 楼
一个不错的选择是避免从int
转换为enum
:例如,如果需要最大值,则可以将x.ordinal()与y.ordinal()比较,并相应地返回x或y。 (您可能需要重新排序值才能使这种比较有意义。)如果这不可能,我会将
MyEnum.values()
存储到静态数组中。评论
如果您从数据库获取int并将其转换为Enum(我认为这是非常常见的任务),则需要int->枚举转换,IMO。
–井上由纪(Yuki Inoue)
18/12/2在5:41
#15 楼
这是与医生相同的答案,但它显示了如何消除可变阵列的问题。如果由于分支预测而首先使用这种方法,则效果几乎没有到零,并且整个代码仅调用一次可变数组values()函数。由于这两个变量都是静态的,因此每次使用此枚举时它们也不会占用n *内存。private static boolean arrayCreated = false;
private static RFMsgType[] ArrayOfValues;
public static RFMsgType GetMsgTypeFromValue(int MessageID) {
if (arrayCreated == false) {
ArrayOfValues = RFMsgType.values();
}
for (int i = 0; i < ArrayOfValues.length; i++) {
if (ArrayOfValues[i].MessageIDValue == MessageID) {
return ArrayOfValues[i];
}
}
return RFMsgType.UNKNOWN;
}
#16 楼
enum MyEnum {
A(0),
B(1);
private final int value;
private MyEnum(int val) {this.value = value;}
private static final MyEnum[] values = MyEnum.values();//cache for optimization
public static final getMyEnum(int value) {
try {
return values[value];//OOB might get triggered
} catch (ArrayOutOfBoundsException e) {
} finally {
return myDefaultEnumValue;
}
}
}
评论
不要使用异常代替边界检查。
– shmosel
17年11月16日在1:19
@shmosel我认为,如果越界越少,则异常会好得多。
–佐索
17年11月17日在14:37
您的信念基于什么?
– shmosel
17年11月17日在16:59
#17 楼
在Kotlin中:enum class Status(val id: Int) {
NEW(0), VISIT(1), IN_WORK(2), FINISHED(3), CANCELLED(4), DUMMY(5);
companion object {
private val statuses = Status.values().associateBy(Status::id)
fun getStatus(id: Int): Status? = statuses[id]
}
}
用法:
val status = Status.getStatus(1)!!
评论
@RyuS。那不是这个问题的重复,