source

Java에서 열거할 Int를 캐스트합니다.

bestscript 2022. 12. 24. 20:35

Java에서 열거할 Int를 캐스트합니다.

다음 열거형에서 Int를 Java에서 열거형으로 캐스트하는 올바른 방법은 무엇입니까?

public enum MyEnum
{
    EnumValue1,
    EnumValue2
}


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

★★를 해 보세요.MyEnum.values()[x]서 ''는x야 한다.0 ★★★★★★★★★★★★★★★★★」1 그입니다).

는 클래스이기 때문에 enum enum ( enum ( values및 ) 。int또는 심지어Integer에뮬러로.

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

정수 값을 지정하려면 다음과 같은 구조를 사용할 수 있습니다.

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

이렇게 하면 돼요.
아이디

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

int id 를을 、 Enum 、 을을을을 。

MyEnum myEnum = MyEnum.fromId(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];
    }
}

Java Enum에는 C++에서와 같은 종류의 Enum-to-int 매핑이 없습니다.

모든 에는 「」, 「」의 열거형이 .values입니다.

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

작동해야 합니다., .int ~ ~까지Enums(으)로 하다

이것은 보통 하는 일이 아니기 때문에 다시 생각해 보겠습니다.int 을 사용하여 int --> enum을 사용하여 int --> enum을 사용하여 int --> enum을 사용합니다.EnumType.values()[intNum]enum > , enum --> int 를 합니다.enumInst.ordinal().

「」가 있기 에, 「」는values()할 수 밖에전용이 아닙니다).는, 「 전용 어레이는 읽기 전용이 아닙니다).★★★★★★★★★★★★★★★★★★·EnumMap mappingenum --> int를 .

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

이것이 제가 취할 계획인 해결책입니다.이는 순차적이지 않은 정수와 함께 작동할 뿐만 아니라 열거값의 기본 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를 enum으로 변환하면 되기 때문에 항상 Map을 메모리에 보관할 필요가 없습니다.맵을 항상 액세스할 수 있어야 하는 경우 언제든지 Enum 클래스의 정적 멤버로 맵을 캐시할 수 있습니다.

다른 사람에게 도움이 될 경우, 여기에 나열되지 않은 옵션에서 Guava의 기능을 사용합니다.

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어떤 행동을 취하든 상관없습니다.

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

반복할 수 있습니다.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
도움이 되었으면 좋겠어요;)

이 실장을 작성했습니다.결측값, 음수값을 허용하고 코드의 일관성을 유지합니다.지도도 캐시됩니다.인터페이스를 사용하여 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;
    }
}

적절한 옵션은, 로부터의 변환을 회피하는 것입니다.int로.enum예를 들어 최대값이 필요한 경우 x.ordinal()과 y.ordinal()을 비교하여 x 또는 y를 반환할 수 있습니다(이러한 비교를 의미 있게 하기 위해 값의 순서를 변경할 필요가 있습니다).

그게 불가능하면 저장해 두겠습니다.MyEnum.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;
}
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;
        }
    }
}

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)!!

언급URL : https://stackoverflow.com/questions/5878952/cast-int-to-enum-in-java