web-dev-qa-db-ja.com

IntをキャストしてJavaのenumにする

次のような列挙型の場合、IntをJavaの列挙型にキャストする正しい方法は何ですか?

public enum MyEnum
{
    EnumValue1,
    EnumValue2
}


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

MyEnum.values()[x]を試してください。ここでx0または1、つまりその列挙型の有効な序数でなければなりません。

Javaでは、実際にはenumはクラスであり(したがってenum値はオブジェクトです)、したがってintIntegerをenumにキャストすることはできません。

551
Thomas

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

整数値を与えたい場合は、以下のような構造を使用できます。

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

あなたはこのように試すことができます。
要素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;
            }
      }

IntをintにしてこのEnumを取得しましょう。

MyEnum myEnum = MyEnum.fromId(5);
27
Piyush Ghediya

値をキャッシュして単純な静的アクセスメソッドを作成します。

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

Javaのenumは、C++の場合と同じようなenum-to-intマッピングを持っていません。

とはいえ、すべてのenumは可能なenum値の配列を返すvaluesメソッドを持っています。

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

うまくいくはずです。それは少し厄介です、そして可能であればintsからEnumsへ(またはその逆)変換しようと試みないでください。

9
Cameron Skinner

これは通常行われていることではないので、私は再考します。ただし、基本的な操作は、EnumType.values()[intNum]を使用したint - > enum、およびenumInst.ordinal()を使用したenum - > intです。

ただし、values()の実装には配列のコピーを渡す以外の選択肢はないため(Java配列は読み取り専用にはなりません)、enum - > intマッピングをキャッシュするためにEnumMapを使用するほうがよいでしょう。

9
Dilum Ranatunga

MyEnum enumValue = MyEnum.values()[x];を使う

7
w.donahue

これが私が計画している解決策です。これは非連続整数で機能するだけでなく、列挙型の値の基になる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クラスの静的メンバーとしていつでもマップをキャッシュできます。

6
jkindwall

それが他の人を助ける場合には、ここにリストされていない私が好むオプションは 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を返すことができます。

5
Chad Befus

以下のように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
これが役に立つことを願っています;)

2
Yashar Aliabasi

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

これは医師と同じ答えですが、可変配列の問題を解決する方法を示しています。あなたが最初に分岐予測のためにこの種のアプローチを使うならば、ifはほとんどまたは全くゼロの効果を持ち、コード全体はmutable array 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;
}
0
Ali Akdurak

これは、インデックスが序数値の問題と同期しなくなることに対処する必要があります。

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's 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;
    }
}
0
Gerrit Brink

コトリンでは:

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)!!
0
CoolMind
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;
        }
    }
}
0
Zoso

良い方法は、intからenumへの変換を避けることです。例えば、最大値が必要なら、x.ordinal()とyを比較します.ordinal()を実行し、それに応じてxまたはyを返します。 (このような比較を意味のあるものにするために、値を並べ替える必要があるかもしれません。)

それが不可能な場合は、MyEnum.values()を静的配列に格納します。