Essayez MyEnum.values()[x]où xdoit être 0ou 1, c'est-à-dire un ordinal valide pour cette énumération.
Notez qu'en Java, les énumérations sont en fait des classes (et les valeurs d'énumération sont donc des objets) et donc vous ne pouvez pas convertir un intou même Integeren une énumération.
+1: Vous voudrez peut-être mettre MyEnum.values()en cache car c'est cher. c'est-à-dire si vous l'appelez des centaines de fois.
Peter Lawrey
6
@PeterLawrey Juste pour être complet, pouvez-vous expliquer pourquoi cela devrait être lent? Je ne vois aucune raison évidente à cela.
Tarrasch
48
@Tarrasch étant donné que les tableaux sont modifiables, values () doit renvoyer une copie du tableau d'éléments au cas où vous le modifieriez. La création de cette copie à chaque fois est relativement coûteuse.
Peter Lawrey
9
@PeterLawrey J'ai utilisé trop de haskell récemment (où tout est immuable)! Merci pour votre explication claire et concise. :)
Tarrasch
comment obtenir le «x»?
Beeing Jk
161
MyEnum.values()[x]est une opération coûteuse. Si les performances sont un problème, vous voudrez peut-être faire quelque chose comme ceci:
Si vous voulez éviter la maintenance du commutateur, alors sur la classe using: private final MyEnum [] myEnumValues = MyEnum.values (); Puis utilisation: myEnum = myEnumValues [i];
Gili Nachum
23
@GiliNachum l'a dit d'une manière étrange, mais le problème avec cette solution est la maintenabilité. Cela va à l'encontre du principe DRY, ce qui signifie que chaque fois que les valeurs d'énumération sont modifiées (réorganisées, valeur (s) ajoutée (s), valeur (s) supprimée (s)), l'instruction switch doit être mise à jour simultanément. Le commentaire de Gili oblige Java à maintenir la cohérence avec la liste des valeurs d'énumération, les modifications apportées aux valeurs d'énumération n'affectent pas du tout cette approche.
Dandre Allison
3
@ LorenzoPolidori, pouvez-vous expliquer pourquoi vous considérez MyEnum.values()[x]comme une opération coûteuse. Je ne sais pas comment cela fonctionne dans les détails, mais pour moi, il semble que l'accès à un élément dans un tableau ne serait pas très grave, alias temps constant. Si le tableau doit être construit, cela prend du temps O (n), qui est le même temps d'exécution que votre solution.
brunsgaard
1
@brunsgaard Je suppose que values()génère un nouveau tableau à chaque fois, car les tableaux sont mutables, il ne serait donc pas sûr de retourner le même plusieurs fois. Les instructions switch ne sont pas nécessairement O (n), elles peuvent être compilées pour sauter des tables. Les affirmations de Lorenzo semblent donc justifiées.
MikeFHay
1
La version de @Johnson Gili ne nécessite aucune modification de code supplémentaire en dehors des modifications de la déclaration Enum. Si vous ajoutez un nouvel élément à l'énumération, myEnum = myEnumValues[i]le même iélément sera renvoyé dans l'énumération sans modifications.
Dandre Allison
45
Si vous voulez donner vos valeurs entières, vous pouvez utiliser une structure comme ci-dessous
publicenum A
{
B(0),
C(10),None(11);int id;private A(int i){id = i;}publicintGetID(){return id;}publicbooleanIsEmpty(){returnthis.equals(A.None);}publicbooleanCompare(int i){return id == i;}publicstatic A GetValue(int _id){
A[]As= A.values();for(int i =0; i <As.length; i++){if(As[i].Compare(_id))returnAs[i];}return A.None;}}
+1 car cela met en évidence le fait que les valeurs n'ont pas à être consécutives.
rhavin
En outre, cela semble être la seule réponse qui fonctionne si vous voulez un ensemble clairsemé (ou répété) de valeurs entières plutôt que d'utiliser les ordinaux par défaut de 0 .. (count-1). Cela peut être important si vous interagissez avec du code existant, par exemple sur un réseau.
benkc
Il convient de souligner que, comme dans les réponses ci-dessus, la mise en cache du résultat de values () vaut probablement la peine, afin d'éviter une allocation de mémoire et une copie de tableau à chaque fois que vous l'invoquez.
benkc
1
Et, selon la longueur de votre énumération, vous souhaiterez peut-être créer un HashMap ou utiliser une recherche binaire ou quelque chose pour cette recherche, plutôt que de faire une recherche linéaire à chaque fois.
benkc
2
Cela devrait être la bonne façon et la meilleure pratique pour convertir int en enum, et je pense que vous pouvez simplifier le problème en statique A GetValue (int _id) {for (A a: A.values () {if (a.getId ( ) == _ id) {return a;}} return null;} Débarrassez-vous des trucs None, isEmpty () et compare ()
Chris.Zou
35
Vous pouvez essayer comme ça.
Créer une classe avec l'ID d'élément.
publicEnumMyEnum{
THIS(5),
THAT(16),
THE_OTHER(35);privateint id;// Could be other data type besides intprivateMyEnum(int id){this.id = id;}publicstaticMyEnum fromId(int id){for(MyEnum type : values()){if(type.getId()== id){return type;}}returnnull;}}
Maintenant, récupérez cette énumération en utilisant id comme int.
C'est la solution que j'utilise maintenant. Mais à mon humble avis, il est moins déroutant si vous ne donnez pas au champ valuesle même nom que la méthode values(). J'utilise cachedValuespour le nom du champ.
ToolmakerSteve
2
Efficace et élégant; copié et collé dans mon projet :) La seule chose que j'ai changé est le fromInt (int i), que je viens d'appeler depuis (int i) car c'est un peu redondant d'avoir int deux fois dans la signature.
pipedreambomb
1
pourquoi ne pas initialiser depuis le début? pourquoi attendre le premier coup?
kaiser
9
Les énumérations Java n'ont pas le même type de mappage enum-à-int qu'en C ++.
Cela dit, toutes valuesles énumérations ont une méthode qui renvoie un tableau de valeurs d'énumération 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 de ints en Enums (ou vice versa) si possible.
Ce n'est pas quelque chose qui se fait habituellement, donc je reconsidérerais. Mais cela étant dit, les opérations fondamentales sont: int -> enum en utilisant EnumType.values () [intNum], et enum -> int en utilisant EnumInst.ordinal ().
Cependant, étant donné que toute implémentation de values () n'a pas d'autre choix que de vous donner une copie du tableau (les tableaux java ne sont jamais en lecture seule), vous seriez mieux servi en utilisant un EnumMap pour mettre en cache le mappage enum -> int.
Re "Ce n'est pas quelque chose qui se fait habituellement": cas courant où cela est utile: l'énumération correspond aux valeurs int stockées dans une base de données.
ToolmakerSteve
@ToolmakerSteve, vous avez absolument raison de dire que les mappages sont requis. Mais voudriez-vous laisser ce type d'encodage à un mappeur OU ou à une boîte à outils / bibliothèque?
Voici la solution avec laquelle je prévois aller. 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 d'énumération.
publicEnumMyEnum{
THIS(5),
THAT(16),
THE_OTHER(35);privateint id;// Could be other data type besides intprivateMyEnum(int id){this.id = id;}publicint getId(){returnthis.id;}publicstaticMap<Integer,MyEnum> buildMap(){Map<Integer,MyEnum> map =newHashMap<Integer,MyEnum>();MyEnum[] values =MyEnum.values();for(MyEnum value : values){
map.put(value.getId(), value);}return map;}}
Je n'ai besoin de convertir les identifiants en énumérations qu'à des moments spécifiques (lors du chargement de données à partir d'un fichier), il n'y a donc aucune raison pour moi de conserver 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.
À mon humble avis, si j'étais préoccupé par l'utilisation de la mémoire, je créerais dynamiquement le HashMap - comme @ossys mais avec un code différent lorsque le cache est nul, puis ajouter une deuxième méthode clearCachedValueslorsque vous avez fini de l'utiliser (qui redéfinit le champ privé sur null). Je considère MyEnum.fromInt(i)plus facile à comprendre que de contourner un objet cartographique.
ToolmakerSteve
6
Au cas où cela aiderait les autres, l'option que je préfère, qui n'est pas répertoriée ici, utilise la fonctionnalité Maps de Guava :
Avec la valeur par défaut que vous pouvez utiliser null, vous pouvez throw IllegalArgumentExceptionou fromIntpouvez retourner un Optional, quel que soit le comportement que vous préférez.
Vous devez mentionner que vous utilisez Guava. Ou vous pouvez utiliser des flux:Map<Integer, MyEnum> reverseLookup = Arrays.stream(MyEnum.values()).collect(Collectors.toMap(MyEnum::getValue, Function.identity()));
shmosel
1
Pourrait aussi vouloir définir une getValue()méthode.
shmosel
@shmosel Oups, j'ai raté la fonction getValue, merci. La saisie de versions génériques dans stackoverflow ne se déroule pas toujours. Ajout d'un commentaire sur l'utilisation de Guava avec un lien. Préférez la méthode Guava aux streams.
Chad Befus
4
Vous pouvez parcourir l' values()énumération et comparer la valeur entière de l'énumération avec celle donnée idci-dessous:
publicenumTestEnum{None(0),Value1(1),Value2(2),Value3(3),Value4(4),Value5(5);privatefinalint value;privateTestEnum(int value){this.value = value;}publicint getValue(){return value;}publicstaticTestEnum getEnum(int value){for(TestEnum e:TestEnum.values()){if(e.getValue()== value)return e;}returnTestEnum.None;//For values out of enum scope}}
Et utilisez comme ceci: TestEnum x = TestEnum.getEnum(4);//Will return TestEnum.Value4
j'espère que cela vous aidera;)
Sur la base de la réponse de @ChadBefus et du commentaire de @shmosel, je recommanderais d'utiliser ceci. (Recherche efficace et fonctionne sur java pur> = 8)
Une bonne option consiste à éviter la conversion de intà enum: par exemple, si vous avez besoin de la valeur maximale, vous pouvez comparer x.ordinal () à y.ordinal () et renvoyer x ou y en conséquence. (Vous devrez peut-être réorganiser vos valeurs pour que cette comparaison soit significative.)
Si ce n'est pas possible, je stockerais MyEnum.values()dans un tableau statique.
Si vous obtenez int de DB et que vous souhaitez le convertir en Enum, ce qui, je pense, est une tâche très courante, vous aurez besoin de int -> conversion d'énumération, IMO ..
Yuki Inoue
0
C'est la même réponse que les médecins, mais elle montre comment éliminer le problème avec les tableaux mutables. Si vous utilisez d'abord ce type d'approche en raison de la prédiction de branche, il aura très peu ou pas d'effet et le code entier n'appellera la fonction de valeurs de tableau mutable () qu'une seule fois. Comme les deux variables sont statiques, elles ne consommeront pas de mémoire n * pour chaque utilisation de cette énumération également.
privatestaticboolean arrayCreated =false;privatestaticRFMsgType[]ArrayOfValues;publicstaticRFMsgTypeGetMsgTypeFromValue(intMessageID){if(arrayCreated ==false){ArrayOfValues=RFMsgType.values();}for(int i =0; i <ArrayOfValues.length; i++){if(ArrayOfValues[i].MessageIDValue==MessageID){returnArrayOfValues[i];}}returnRFMsgType.UNKNOWN;}
A écrit cette implémentation. Il permet les valeurs manquantes, les valeurs négatives et maintient la cohérence du code. La carte est également mise en cache. Utilise une interface et a besoin de Java 8.
Réponses:
Essayez
MyEnum.values()[x]
oùx
doit être0
ou1
, c'est-à-dire un ordinal valide pour cette énumération.Notez qu'en Java, les énumérations sont en fait des classes (et les valeurs d'énumération sont donc des objets) et donc vous ne pouvez pas convertir un
int
ou mêmeInteger
en une énumération.la source
MyEnum.values()
en cache car c'est cher. c'est-à-dire si vous l'appelez des centaines de fois.MyEnum.values()[x]
est une opération coûteuse. Si les performances sont un problème, vous voudrez peut-être faire quelque chose comme ceci:la source
MyEnum.values()[x]
comme une opération coûteuse. Je ne sais pas comment cela fonctionne dans les détails, mais pour moi, il semble que l'accès à un élément dans un tableau ne serait pas très grave, alias temps constant. Si le tableau doit être construit, cela prend du temps O (n), qui est le même temps d'exécution que votre solution.values()
génère un nouveau tableau à chaque fois, car les tableaux sont mutables, il ne serait donc pas sûr de retourner le même plusieurs fois. Les instructions switch ne sont pas nécessairement O (n), elles peuvent être compilées pour sauter des tables. Les affirmations de Lorenzo semblent donc justifiées.myEnum = myEnumValues[i]
le mêmei
élément sera renvoyé dans l'énumération sans modifications.Si vous voulez donner vos valeurs entières, vous pouvez utiliser une structure comme ci-dessous
la source
Vous pouvez essayer comme ça.
Créer une classe avec l'ID d'élément.
Maintenant, récupérez cette énumération en utilisant id comme int.
la source
Je mets en cache les valeurs et crée une méthode d'accès statique simple:
la source
values
le même nom que la méthodevalues()
. J'utilisecachedValues
pour le nom du champ.Les énumérations Java n'ont pas le même type de mappage enum-à-int qu'en C ++.
Cela dit, toutes
values
les énumérations ont une méthode qui renvoie un tableau de valeurs d'énumération possibles, doncdevrait marcher. C'est un peu méchant et il pourrait être préférable de ne pas essayer de convertir de
int
s enEnum
s (ou vice versa) si possible.la source
Ce n'est pas quelque chose qui se fait habituellement, donc je reconsidérerais. Mais cela étant dit, les opérations fondamentales sont: int -> enum en utilisant EnumType.values () [intNum], et enum -> int en utilisant EnumInst.ordinal ().
Cependant, étant donné que toute implémentation de values () n'a pas d'autre choix que de vous donner une copie du tableau (les tableaux java ne sont jamais en lecture seule), vous seriez mieux servi en utilisant un EnumMap pour mettre en cache le mappage enum -> int.
la source
Utilisation
MyEnum enumValue = MyEnum.values()[x];
la source
Voici la solution avec laquelle je prévois aller. 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 d'énumération.
Je n'ai besoin de convertir les identifiants en énumérations qu'à des moments spécifiques (lors du chargement de données à partir d'un fichier), il n'y a donc aucune raison pour moi de conserver 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.
la source
clearCachedValues
lorsque vous avez fini de l'utiliser (qui redéfinit le champ privé sur null). Je considèreMyEnum.fromInt(i)
plus facile à comprendre que de contourner un objet cartographique.Au cas où cela aiderait les autres, l'option que je préfère, qui n'est pas répertoriée ici, utilise la fonctionnalité Maps de Guava :
Avec la valeur par défaut que vous pouvez utiliser
null
, vous pouvezthrow IllegalArgumentException
oufromInt
pouvez retourner unOptional
, quel que soit le comportement que vous préférez.la source
Map<Integer, MyEnum> reverseLookup = Arrays.stream(MyEnum.values()).collect(Collectors.toMap(MyEnum::getValue, Function.identity()));
getValue()
méthode.Vous pouvez parcourir l'
values()
énumération et comparer la valeur entière de l'énumération avec celle donnéeid
ci-dessous:Et utilisez comme ceci:
TestEnum x = TestEnum.getEnum(4);//Will return TestEnum.Value4
j'espère que cela vous aidera;)
la source
Sur la base de la réponse de @ChadBefus et du commentaire de @shmosel, je recommanderais d'utiliser ceci. (Recherche efficace et fonctionne sur java pur> = 8)
la source
Une bonne option consiste à éviter la conversion de
int
àenum
: par exemple, si vous avez besoin de la valeur maximale, vous pouvez comparer x.ordinal () à y.ordinal () et renvoyer x ou y en conséquence. (Vous devrez peut-être réorganiser vos valeurs pour que cette comparaison soit significative.)Si ce n'est pas possible, je stockerais
MyEnum.values()
dans un tableau statique.la source
C'est la même réponse que les médecins, mais elle montre comment éliminer le problème avec les tableaux mutables. Si vous utilisez d'abord ce type d'approche en raison de la prédiction de branche, il aura très peu ou pas d'effet et le code entier n'appellera la fonction de valeurs de tableau mutable () qu'une seule fois. Comme les deux variables sont statiques, elles ne consommeront pas de mémoire n * pour chaque utilisation de cette énumération également.
la source
la source
À Kotlin:
Usage:
la source
A écrit cette implémentation. Il permet les valeurs manquantes, les valeurs négatives et maintient la cohérence du code. La carte est également mise en cache. Utilise une interface et a besoin de Java 8.
Enum
Interface
la source