364

给定以下枚举,将 Int 转换为 Java 中的枚举的正确方法是什么?

public enum MyEnum
{
    EnumValue1,
    EnumValue2
}


MyEnum enumValue = (MyEnum) x; //Doesn't work???
4

17 回答 17

623

尝试MyEnum.values()[x]where xmust be 0or 1,即该枚举的有效序数。

请注意,在 Java 中,枚举实际上是类(因此枚举值是对象),因此您不能将enumint或什Integer至强制转换为 enum。

于 2011-05-04T05:28:01.317 回答
177

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;
    }
}
于 2012-01-06T18:09:03.770 回答
50

如果要给出整数值,可以使用如下结构

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;
        }
}
于 2013-01-08T14:36:02.373 回答
46

你可以这样试试。
创建具有元素 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 作为 int 获取此枚举。

MyEnum myEnum = MyEnum.fromId(5);
于 2015-11-03T06:27:37.000 回答
22

我缓存这些值并创建一个简单的静态访问方法:

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];
    }
}
于 2012-12-18T21:31:53.967 回答
11

Java 枚举没有与 C++ 中相同的枚举到整数映射。

也就是说,所有枚举都有一个values返回可能枚举值数组的方法,所以

MyEnum enumValue = MyEnum.values()[x];

应该管用。这有点讨厌,如果可能的话,最好不要尝试从ints 转换为Enums (反之亦然)。

于 2011-05-04T05:29:53.390 回答
9

这不是通常会做的事情,所以我会重新考虑。但话虽如此,基本操作是: int --> enum usingEnumType.values()[intNum]和 enum --> int using enumInst.ordinal()

但是,由于 的任何实现values()都别无选择,只能为您提供数组的副本(java 数组永远不是只读的),因此最好使用 anEnumMap来缓存 enum --> int 映射。

于 2011-05-04T05:32:32.343 回答
8

采用MyEnum enumValue = MyEnum.values()[x];

于 2011-05-04T05:29:08.903 回答
6

这是我计划采用的解决方案。这不仅适用于非顺序整数,还适用于您可能希望用作枚举值的基础 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 int getId() {
        return this.id;
    }

    public static Map<Integer, MyEnum> buildMap() {
        Map<Integer, MyEnum> map = new HashMap<Integer, MyEnum>();
        MyEnum[] values = MyEnum.values();
        for (MyEnum value : values) {
            map.put(value.getId(), value);
        }

        return map;
    }
}

我只需要在特定时间(从文件加载数据时)将 id 转换为枚举,因此我没有理由始终将 Map 保留在内存中。如果您确实需要始终可以访问地图,则始终可以将其缓存为 Enum 类的静态成员。

于 2015-02-08T18:45:06.463 回答
6

如果它对其他人有帮助,我更喜​​欢的选项(此处未列出)使用Guava 的 Maps 功能

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 ImmutableMap<Integer, MyEnum> reverseLookup = 
            Maps.uniqueIndex(Arrays.asList(MyEnum.values())), MyEnum::getValue);

    public static MyEnum fromInt(final int id) {
        return reverseLookup.getOrDefault(id, OPTION_1);
    }
}

使用你可以使用的默认值null,你可以throw IllegalArgumentException或者你fromInt可以返回一个Optional,无论你喜欢什么行为。

于 2017-11-16T00:37:40.273 回答
5

根据@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());
    }
}
于 2018-12-02T06:06:11.767 回答
4

您可以迭代values()枚举并将枚举的整数值与给定的值进行比较,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
我希望这会有所帮助;)

于 2017-06-19T16:45:17.737 回答
3

写了这个实现。它允许缺失值、负值并保持代码一致。地图也被缓存。使用接口并需要 Java 8。

枚举

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;
    }
}
于 2016-04-06T17:18:11.030 回答
0

一个好的选择是避免intto转换enum:例如,如果您需要最大值,您可以将 x.ordinal() 与 y.ordinal() 进行比较并相应地返回 x 或 y。(您可能需要重新排序您的值以使此类比较有意义。)

如果那不可能,我会存储MyEnum.values()到一个静态数组中。

于 2012-07-02T09:52:43.277 回答
0

这与医生的答案相同,但它显示了如何消除可变数组的问题。如果您使用这种方法,因为首先是分支预测,如果将几乎没有影响到零,并且整个代码只调用一次可变数组 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;
}
于 2013-05-22T18:45:58.950 回答
0
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;
        }
    }
}
于 2015-12-14T23:10:59.560 回答
0

在科特林:

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)!!
于 2019-03-12T09:20:16.197 回答