Pruebe MyEnum.values()[x]dónde xdebe estar 0o 1, es decir, un ordinal válido para esa enumeración.
Tenga en cuenta que en Java las enumeraciones en realidad son clases (y los valores de enumeración son, por lo tanto, objetos) y, por lo tanto, no puede convertir una enumeración into incluso Integera una enumeración.
+1: es posible que desee almacenar en caché MyEnum.values()ya que es costoso. es decir, si lo llamas cientos de veces.
Peter Lawrey
66
@PeterLawrey Solo para completar, ¿puedes explicar por qué debería ser lento? No veo una razón obvia para ello.
Tarrasch
48
@Tarrasch como las matrices son mutables, los valores () deben devolver una copia de la matriz de elementos en caso de que lo cambie. Crear esta copia cada vez es relativamente costoso.
Peter Lawrey
99
@PeterLawrey ¡He estado usando mucho haskell últimamente (donde todo es inmutable)! Gracias por su explicación clara y concisa. :)
Tarrasch
¿Cómo obtener la 'x'?
Beeing Jk
161
MyEnum.values()[x]Es una operación costosa. Si el rendimiento es una preocupación, es posible que desee hacer algo como esto:
Si desea evitar el mantenimiento del conmutador, en la clase using: private final MyEnum [] myEnumValues = MyEnum.values (); Entonces uso: myEnum = myEnumValues [i];
Gili Nachum
23
@GiliNachum lo dijo de una manera extraña, pero el problema con esta solución es la mantenibilidad. Va en contra del principio DRY, lo que significa que cada vez que se cambian los valores de enumeración (reordenados, valor (es) agregado (s), valor (es) eliminado) la declaración de cambio debe actualizarse simultáneamente. El comentario de Gili obliga a Java a mantener la coherencia con la lista de valores de enumeración, los cambios en los valores de enumeración no afectan en absoluto ese enfoque.
Dandre Allison
3
@LorenzoPolidori, ¿Puede explicar por qué lo considera MyEnum.values()[x]una operación costosa? No sé cómo funciona en detalles, pero para mí parece que acceder a un elemento en una matriz no sería gran cosa, también conocido como tiempo constante. Si la matriz tiene que compilarse, toma O (n) tiempo, que es el mismo tiempo de ejecución que su solución.
brunsgaard
1
@brunsgaard supongo que values()genera una nueva matriz cada vez, porque las matrices son mutables, por lo que no sería seguro devolver la misma varias veces. Las instrucciones de cambio no son necesariamente O (n), se pueden compilar para saltar tablas. Entonces las afirmaciones de Lorenzo parecen justificadas.
MikeFHay
1
La versión de @Johnson Gili no requiere ningún cambio de código adicional fuera de los cambios en la declaración de Enum. Si agrega un nuevo elemento a la enumeración, myEnum = myEnumValues[i]aún devolverá el ielemento th en la enumeración sin cambios.
Dandre Allison
45
Si desea dar sus valores enteros, puede usar una estructura como la siguiente
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 porque resalta el hecho de que los valores no tienen que ser consecutivos.
rhavin
Además, esta parece ser la única respuesta que funciona si desea un conjunto escaso (o repetido) de valores enteros en lugar de utilizar los ordinales predeterminados de 0 .. (cuenta-1). Eso puede ser importante si está interactuando con el código existente, como a través de una red.
benkc
Vale la pena señalar que, como en las respuestas anteriores, es probable que valga la pena almacenar en caché el resultado de los valores (), para evitar una asignación de memoria y una copia de matriz cada vez que lo invoque.
benkc
1
Y, dependiendo de la longitud de su enumeración, es posible que desee crear un HashMap o usar una búsqueda binaria o algo para esta búsqueda, en lugar de hacer una búsqueda lineal cada vez.
benkc
2
Esta debería ser la forma correcta y la mejor práctica para convertir int a enum, y creo que puede simplificar el problema mediante la estática pública A GetValue (int _id) {for (A a: A.values () {if (a.getId ( ) == _ id) {return a;}} return null;} Deshazte de las cosas None, isEmpty () y compare ().
Chris.Zou
35
Puedes intentarlo así.
Crear clase con elemento id.
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;}}
Ahora obtenga esta enumeración usando id como int.
Esta es la solución que uso ahora. Pero en mi humilde opinión, es menos confuso si no le das al campo valuesel mismo nombre que el método values(). Yo uso cachedValuespara el nombre del campo.
ToolmakerSteve
2
Eficiente y elegante; copiado y pegado en mi proyecto :) Lo único que cambié es fromInt (int i), al que acabo de llamar desde (int i) porque es un poco redundante tener int dos veces en la firma.
pipedreambomb
1
¿Por qué no inicializar desde el principio? ¿Por qué esperar el primer golpe?
kaiser
9
Las enumeraciones de Java no tienen el mismo tipo de asignación de enumeración a int que tienen en C ++.
Dicho esto, todas las enumeraciones tienen un valuesmétodo que devuelve una matriz de posibles valores de enumeración, por lo que
MyEnum enumValue =MyEnum.values()[x];
Deberia trabajar. Es un poco desagradable y podría ser mejor no intentar convertir de ints a Enums (o viceversa) si es posible.
Esto no es algo que generalmente se hace, así que lo reconsideraría. Pero dicho esto, las operaciones fundamentales son: int -> enum usando EnumType.values () [intNum], y enum -> int usando enumInst.ordinal ().
Sin embargo, dado que cualquier implementación de valores () no tiene más remedio que darle una copia de la matriz (las matrices java nunca son de solo lectura), será mejor que use un EnumMap para almacenar en caché la asignación enum -> int.
Re "Esto no es algo que generalmente se hace": caso común donde es útil: enum corresponde a valores int almacenados en una base de datos.
ToolmakerSteve
@ToolmakerSteve tiene toda la razón en que se requieren las asignaciones. ¿Pero le gustaría dejar ese tipo de codificación a algún mapeador OR o algún kit de herramientas / biblioteca?
Aquí está la solución con la que planeo ir. Esto no solo funciona con enteros no secuenciales, sino que también debería funcionar con cualquier otro tipo de datos que desee utilizar como ID subyacente para sus valores de enumeración.
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;}}
Solo necesito convertir las identificaciones en enumeraciones en momentos específicos (cuando se cargan datos de un archivo), por lo que no hay ninguna razón para mantener el Mapa en la memoria en todo momento. Si necesita que el mapa esté accesible en todo momento, siempre puede almacenarlo en caché como miembro estático de su clase Enum.
En mi humilde opinión, si me preocupara el uso de la memoria, crearía dinámicamente el HashMap, como @ossys pero con un código diferente cuando el caché es nulo, luego agregaría un segundo método clearCachedValuescuando termine de usarlo (eso establece el campo privado de nuevo a nulo). Considero MyEnum.fromInt(i)más fácil de entender que pasar un objeto de mapa.
Deberías mencionar que estás usando guayaba. O puede usar transmisiones:Map<Integer, MyEnum> reverseLookup = Arrays.stream(MyEnum.values()).collect(Collectors.toMap(MyEnum::getValue, Function.identity()));
shmosel
1
Podría querer definir un getValue()método también.
shmosel
@shmosel Vaya, me perdí la función getValue, gracias. Escribir versiones genéricas en stackoverflow no siempre funciona. Comentario agregado sobre el uso de Guava con un enlace. Prefiere el método de la guayaba a las corrientes.
Chad Befus
4
Puede iterar sobre values()enum y comparar el valor entero de enum con los dados ida continuación:
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}}
Y use así: TestEnum x = TestEnum.getEnum(4);//Will return TestEnum.Value4
espero que esto ayude;)
Una buena opción es evitar la conversión de inta enum: por ejemplo, si necesita el valor máximo, puede comparar x.ordinal () con y.ordinal () y devolver x o y en consecuencia. (Es posible que deba reordenar sus valores para que dicha comparación sea significativa).
Si eso no es posible, lo almacenaría MyEnum.values()en una matriz estática.
Si obtiene int de DB y desea convertirlo en Enum, que creo que es una tarea muy común, necesitará int -> enum conversion, IMO ..
Yuki Inoue
0
Esta es la misma respuesta que los médicos, pero muestra cómo eliminar el problema con las matrices mutables. Si usa este tipo de enfoque debido a la predicción de ramificación, primero tendrá un efecto de muy poco a cero y el código completo solo llama a los valores de matriz mutable () funcionan solo una vez. Como ambas variables son estáticas, tampoco consumirán n * memoria para cada uso de esta enumeración.
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;}
Escribió esta implementación. Permite valores perdidos, valores negativos y mantiene el código consistente. El mapa también se almacena en caché. Utiliza una interfaz y necesita Java 8.
Respuestas:
Pruebe
MyEnum.values()[x]
dóndex
debe estar0
o1
, es decir, un ordinal válido para esa enumeración.Tenga en cuenta que en Java las enumeraciones en realidad son clases (y los valores de enumeración son, por lo tanto, objetos) y, por lo tanto, no puede convertir una enumeración
int
o inclusoInteger
a una enumeración.fuente
MyEnum.values()
ya que es costoso. es decir, si lo llamas cientos de veces.MyEnum.values()[x]
Es una operación costosa. Si el rendimiento es una preocupación, es posible que desee hacer algo como esto:fuente
MyEnum.values()[x]
una operación costosa? No sé cómo funciona en detalles, pero para mí parece que acceder a un elemento en una matriz no sería gran cosa, también conocido como tiempo constante. Si la matriz tiene que compilarse, toma O (n) tiempo, que es el mismo tiempo de ejecución que su solución.values()
genera una nueva matriz cada vez, porque las matrices son mutables, por lo que no sería seguro devolver la misma varias veces. Las instrucciones de cambio no son necesariamente O (n), se pueden compilar para saltar tablas. Entonces las afirmaciones de Lorenzo parecen justificadas.myEnum = myEnumValues[i]
aún devolverá eli
elemento th en la enumeración sin cambios.Si desea dar sus valores enteros, puede usar una estructura como la siguiente
fuente
Puedes intentarlo así.
Crear clase con elemento id.
Ahora obtenga esta enumeración usando id como int.
fuente
Guardo en caché los valores y creo un método de acceso estático simple:
fuente
values
el mismo nombre que el métodovalues()
. Yo usocachedValues
para el nombre del campo.Las enumeraciones de Java no tienen el mismo tipo de asignación de enumeración a int que tienen en C ++.
Dicho esto, todas las enumeraciones tienen un
values
método que devuelve una matriz de posibles valores de enumeración, por lo queDeberia trabajar. Es un poco desagradable y podría ser mejor no intentar convertir de
int
s aEnum
s (o viceversa) si es posible.fuente
Esto no es algo que generalmente se hace, así que lo reconsideraría. Pero dicho esto, las operaciones fundamentales son: int -> enum usando EnumType.values () [intNum], y enum -> int usando enumInst.ordinal ().
Sin embargo, dado que cualquier implementación de valores () no tiene más remedio que darle una copia de la matriz (las matrices java nunca son de solo lectura), será mejor que use un EnumMap para almacenar en caché la asignación enum -> int.
fuente
Utilizar
MyEnum enumValue = MyEnum.values()[x];
fuente
Aquí está la solución con la que planeo ir. Esto no solo funciona con enteros no secuenciales, sino que también debería funcionar con cualquier otro tipo de datos que desee utilizar como ID subyacente para sus valores de enumeración.
Solo necesito convertir las identificaciones en enumeraciones en momentos específicos (cuando se cargan datos de un archivo), por lo que no hay ninguna razón para mantener el Mapa en la memoria en todo momento. Si necesita que el mapa esté accesible en todo momento, siempre puede almacenarlo en caché como miembro estático de su clase Enum.
fuente
clearCachedValues
cuando termine de usarlo (eso establece el campo privado de nuevo a nulo). ConsideroMyEnum.fromInt(i)
más fácil de entender que pasar un objeto de mapa.En caso de que ayude a otros, la opción que prefiero, que no se encuentra aquí, utiliza la funcionalidad de Mapas de Guava :
Con el valor predeterminado que puede usar
null
, puedethrow IllegalArgumentException
ofromInt
puede devolver unOptional
comportamiento que prefiera.fuente
Map<Integer, MyEnum> reverseLookup = Arrays.stream(MyEnum.values()).collect(Collectors.toMap(MyEnum::getValue, Function.identity()));
getValue()
método también.Puede iterar sobre
values()
enum y comparar el valor entero de enum con los dadosid
a continuación:Y use así:
TestEnum x = TestEnum.getEnum(4);//Will return TestEnum.Value4
espero que esto ayude;)
fuente
Según la respuesta de @ChadBefus y el comentario de @shmosel, recomendaría usar esto. (Búsqueda eficiente, y funciona en Java puro> = 8)
fuente
Una buena opción es evitar la conversión de
int
aenum
: por ejemplo, si necesita el valor máximo, puede comparar x.ordinal () con y.ordinal () y devolver x o y en consecuencia. (Es posible que deba reordenar sus valores para que dicha comparación sea significativa).Si eso no es posible, lo almacenaría
MyEnum.values()
en una matriz estática.fuente
Esta es la misma respuesta que los médicos, pero muestra cómo eliminar el problema con las matrices mutables. Si usa este tipo de enfoque debido a la predicción de ramificación, primero tendrá un efecto de muy poco a cero y el código completo solo llama a los valores de matriz mutable () funcionan solo una vez. Como ambas variables son estáticas, tampoco consumirán n * memoria para cada uso de esta enumeración.
fuente
fuente
En Kotlin:
Uso:
fuente
Escribió esta implementación. Permite valores perdidos, valores negativos y mantiene el código consistente. El mapa también se almacena en caché. Utiliza una interfaz y necesita Java 8.
Enum
Interfaz
fuente