Вставить Int для перечисления в Java

Каков правильный способ преобразования Int в enum в Java с учетом следующего перечисления?

public enum MyEnum
{
    EnumValue1,
    EnumValue2
}


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

Ответ 1

Попробуйте MyEnum.values()[x], где x должен быть 0 или 1, то есть действительный порядковый номер для этого перечисления.

Обратите внимание, что в Java перечисления на самом деле являются классами (и значения перечисления, таким образом, являются объектами), и поэтому вы не можете передать int или даже Integer в перечисление.

Ответ 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;
    }
}

Ответ 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;
        }
}

Ответ 4

Вы можете попробовать это.
Создать класс с идентификатором элемента.

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

Теперь выберите этот Enum, используя id как int.

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

Ответ 6

В перечислениях Java нет такого же типа отображения enum-to-int, что и в С++.

Тем не менее, все перечисления имеют метод values, который возвращает массив возможных значений перечисления, поэтому

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

должен работать. Это немного неприятно, и было бы лучше не пытаться конвертировать из int в Enum (или наоборот), если это возможно.

Ответ 7

Это не то, что обычно делается, поэтому я бы пересмотрел. Но, сказав это, основными операциями являются: int → enum, используя EnumType.values ​​() [intNum], и enum → int, используя enumInst.ordinal().

Однако, поскольку любая реализация значений() не имеет другого выбора, кроме как предоставить вам копию массива (массивы java никогда не доступны только для чтения), вам лучше будет использовать EnumMap для кэширования перечисления → int отображение.

Ответ 8

Используйте MyEnum enumValue = MyEnum.values()[x];

Ответ 9

Вот решение, с которым я планирую пойти. Это не только работает с непоследовательными целыми числами, но и должно работать с любым другим типом данных, который вы можете использовать в качестве базового идентификатора для своих значений перечисления.

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 в перечисления в определенное время (при загрузке данных из файла), поэтому нет никаких оснований для того, чтобы я всегда сохранял карту в памяти. Если вам нужна карта, чтобы быть доступной во все времена, вы всегда можете кэшировать ее как статический член вашего класса Enum.

Ответ 10

В случае, если это помогает другим, вариант, который я предпочитаю, который не указан здесь, использует функциональные возможности 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, независимо от того, какое поведение вы предпочитаете.

Ответ 11

Вы можете перечислить значение 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
Надеюсь, это поможет;)

Ответ 12

Хорошим вариантом является избежать преобразования от int до enum: например, если вам нужно максимальное значение, вы можете сравнить x.ordinal() с y.ordinal() и возвращают x или y соответственно. (Возможно, вам придется переупорядочить ваши значения, чтобы сделать такое сравнение значимым.)

Если это невозможно, я бы сохранил MyEnum.values() в статическом массиве.

Ответ 13

Это тот же самый ответ, что и врачи, но он показывает, как устранить проблему с изменяемыми массивами. Если вы используете такой подход из-за предварительного предсказания ветвления, если у него будет очень мало нулевого эффекта, а весь код вызывает только функцию изменяемых значений массива() только один раз. Поскольку обе переменные являются статическими, они не будут потреблять 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;
}

Ответ 14

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

Ответ 15

Это должно привести к тому, что индексы не синхронизируются с проблемой порядкового значения.

package service.manager;

public enum Command {
    PRINT_FOO(0),
    PRINT_BAR(2),
    PRINT_BAZ(3);

    public int intVal;
    Command(int intVal){
        this.intVal = intVal;
    }

    /**
     * Functionality to ascertain an enum from an int
     * The static block initializes the array indexes to correspond with it according ordinal value
     * Simply use Command.values[index] or get the int value by e.g. Command.PRINT_FOO.intVal;
     * */
    public static Command values[];
    static{
        int maxVal = -1;
        for(Command cmd : Command.values())
            if(maxVal < cmd.intVal)
                maxVal = cmd.intVal;

        values = new Command[maxVal + 1];

        for(Command cmd : Command.values())
            values[cmd.intVal] = cmd;
    }
}

Ответ 16

Основываясь на ответе @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());
    }
}