web-dev-qa-db-fra.com

Transmettre Int pour énumérer dans Java

Quelle est la bonne façon de convertir un Int en une énumération dans Java, en fonction de l'énumération suivante?

public enum MyEnum
{
    EnumValue1,
    EnumValue2
}


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

Essayez MyEnum.values()[x]x doit être 0 ou 1, c’est-à-dire un ordinal valide pour cette énumération.

Notez que dans Java, les énumérations sont en fait des classes (et les valeurs enum sont donc des objets) et vous ne pouvez donc pas convertir un int ou même Integer en un enum.

557
Thomas

MyEnum.values()[x] est une opération coûteuse. Si la performance est une préoccupation, vous pouvez faire quelque chose comme ceci:

public enum MyEnum {
    EnumValue1,
    EnumValue2;

    public static MyEnum fromInteger(int x) {
        switch(x) {
        case 0:
            return EnumValue1;
        case 1:
            return EnumValue2;
        }
        return null;
    }
}
153
Lorenzo Polidori

Si vous voulez donner vos valeurs entières, vous pouvez utiliser une structure comme ci-dessous

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

Vous pouvez essayer comme ça.
Créer une classe avec l’identificateur d’élément.

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

Maintenant, récupérez cet Enum en utilisant id comme int.

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

Je cache les valeurs et crée une méthode d'accès statique simple:

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

Les énumérations Java n'ont pas le même type de mappage énumération-à-int qu'en C++.

Cela dit, toutes les énumérations ont une méthode values qui renvoie un tableau de valeurs d’énum possibles, donc

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

devrait marcher. C'est un peu méchant et il pourrait être préférable de ne pas essayer de convertir si ints en Enums (ou vice versa) si possible.

9
Cameron Skinner

Ce n'est pas quelque chose qui est généralement fait, donc je reconsidérerais. Cela étant dit, les opérations fondamentales sont les suivantes: int -> enum utilisant EnumType.values ​​() [intNum], et enum -> int utilisant enumInst.ordinal ().

Cependant, étant donné que toute implémentation de values ​​() n'a d'autre choix que de vous fournir une copie du tableau (les tableaux Java ne sont jamais en lecture seule), il serait préférable de vous servir d'un EnumMap pour mettre en cache le mappage enum -> int.

9
Dilum Ranatunga

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

7
w.donahue

Voici la solution que je prévois d’utiliser. Non seulement cela fonctionne avec des entiers non séquentiels, mais cela devrait fonctionner avec tout autre type de données que vous voudrez peut-être utiliser comme id sous-jacent pour vos valeurs enum.

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

Je n'ai besoin que de convertir les identifiants en enum à des moments précis (lors du chargement de données à partir d'un fichier), il n'y a donc aucune raison pour que je garde la carte en mémoire à tout moment. Si vous avez besoin que la carte soit accessible à tout moment, vous pouvez toujours la mettre en cache en tant que membre statique de votre classe Enum.

6
jkindwall

Si cela peut aider les autres, l’option que je préfère, qui ne figure pas ici, utilise fonctionnalité de Guava's 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);
    }
}

Par défaut, vous pouvez utiliser null, vous pouvez throw IllegalArgumentException ou votre fromInt peut renvoyer un Optional, quel que soit le comportement que vous préférez.

6
Chad Befus

Vous pouvez itérer sur values() of enum et comparer la valeur entière de enum avec donné id comme ci-dessous:

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

Et utilisez juste comme ça:
TestEnum x = TestEnum.getEnum(4);//Will return TestEnum.Value4
J'espère que ça aide ;)

2
Yashar Aliabbasi

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

Usage:

val status = Status.getStatus(1)!!
1
CoolMind

Basé sur la réponse de @ChadBefus et le commentaire de @shmosel, je recommanderais d'utiliser ceci. (Recherche efficace, et fonctionne sur Java> = 8 pur)

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

C’est la même réponse que les médecins mais elle montre comment éliminer le problème des tableaux mutables. Si vous utilisez ce type d’approche en raison de la prédiction de branche, commencez par avoir très peu d’effet nul et le code entier n’appelle la fonction valeurs mutables () qu’une seule fois. Comme les deux variables sont statiques, elles ne consomment pas non plus n * memory pour chaque utilisation de cette énumération.

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

Cela devrait permettre aux index de ne plus être synchronisés avec le problème des valeurs ordinales.

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

Une bonne option consiste à éviter la conversion de int en enum: par exemple, si vous avez besoin de la valeur maximale, comparez x.ordinal () à y.ordinal ( ) et retourne x ou y en conséquence. (Vous devrez peut-être réorganiser vos valeurs pour rendre cette comparaison significative.)

Si ce n'est pas possible, je stockerais MyEnum.values() dans un tableau statique.

0