Tente MyEnum.values()[x]onde xdeve estar 0ou 1, ou seja, um ordinal válido para essa enumeração.
Note-se que em enums Java realmente são classes (e valores de enumeração são, portanto, objetos) e, portanto, você não pode lançar um intou até mesmo Integerpara um ENUM.
+1: convém armazenar em cache MyEnum.values()como caro. ou seja, se você chamá-lo centenas de vezes.
Peter Lawrey
6
@PeterLawrey Apenas por completude, você pode explicar por que deve ser lento? Não vejo razão óbvia para isso.
Tarrasch
48
@ Tarrasch como matrizes são mutáveis, values () devem retornar uma cópia da matriz de elementos para o caso de você alterá-la. Criar essa cópia a cada vez é relativamente caro.
Peter Lawrey
9
@ PeterLawrey eu tenho usado muito haskell ultimamente (onde tudo é imutável)! Obrigado pela sua explicação clara e concisa. :)
Tarrasch
como obter o 'x'?
Beeing Jk
161
MyEnum.values()[x]é uma operação cara. Se o desempenho for uma preocupação, convém fazer algo assim:
Se você quiser evitar a manutenção do switch, na classe using: private final MyEnum [] myEnumValues = MyEnum.values (); Então use: myEnum = myEnumValues [i];
Gili Nachum
23
A @GiliNachum disse isso de uma maneira estranha, mas o problema com esta solução é a manutenção. Isso vai contra o princípio DRY, que significa que sempre que os valores da enumeração são alterados (reordenados, valor agregado, valor removido), a instrução switch deve ser atualizada simultaneamente. O comentário de Gili força o Java a manter a consistência com a lista de valores de enumeração, alterações nos valores de enumeração não afetam essa abordagem.
Dandre Allison
3
@ LorenzoPolidori, você pode explicar por que considera MyEnum.values()[x]uma operação cara? Não sei como funciona em detalhes, mas para mim parece que acessar um elemento em uma matriz não seria grande coisa, também conhecido como tempo constante. Se a matriz precisar ser compilada, leva-se tempo O (n), que é o mesmo tempo de execução da sua solução.
Brunsgaard 04/10
1
@brunsgaard Suponho que values()gera uma nova matriz de cada vez, porque as matrizes são mutáveis, portanto não seria seguro retornar o mesmo várias vezes. As instruções de switch não são necessariamente O (n), elas podem ser compiladas para saltar tabelas. Portanto, as alegações de Lorenzo parecem justificadas.
precisa saber é o seguinte
1
A versão de @Johnson Gili não requer nenhuma alteração adicional de código fora das alterações na declaração Enum. Se você adicionar um novo item ao enum, myEnum = myEnumValues[i]ainda retornará o ith item no Enum sem alterações.
Dandre Allison
45
Se você deseja fornecer valores inteiros, pode usar uma estrutura como a abaixo
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 destaca o fato de que os valores não precisam ser consecutivos.
rhavin
Além disso, esta parece ser a única resposta que funciona se você deseja um conjunto esparso (ou repetido) de valores inteiros, em vez de usar os ordinais padrão de 0 .. (contagem-1). Isso pode ser importante se você estiver interagindo com o código existente, como em uma rede.
benkc
Vale ressaltar que, como nas respostas acima, o armazenamento em cache do resultado de values () provavelmente vale a pena, para evitar uma alocação de memória e cópia de matriz sempre que você o invocar.
benkc
1
E, dependendo do tamanho da sua enumeração, convém criar um HashMap ou usar uma pesquisa binária ou algo para essa pesquisa, em vez de fazer uma pesquisa linear todas as vezes.
benkc
2
Esse deve ser o caminho certo e a melhor prática para converter int para enum, e acho que você pode simplificar o problema por meio de estática pública A GetValue (int _id) {para (A a: A.values () {if (a.getId ( ) == _ id) {return a;}} return null;} se livrar do None, isEmpty () e compare () coisas.
Chris.Zou
35
Você pode tentar assim.
Criar classe com o ID do elemento.
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;}}
Esta é a solução que eu uso agora. Mas IMHO é menos confuso se você não der ao campo valueso mesmo nome que o método values(). Eu uso cachedValuespara o nome do campo.
Home
2
Eficiente e elegante; copiado e colado no meu projeto :) A única coisa que mudei é fromInt (int i), que acabei de chamar de (int i) porque é um pouco redundante ter int duas vezes na assinatura.
Pipedreambomb
1
por que não inicializar do começo? por que esperar o primeiro hit?
Kaiser #
9
As enumerações Java não têm o mesmo tipo de mapeamento enum-para-int do C ++.
Dito isto, todas as enumerações têm um valuesmétodo que retorna uma matriz de possíveis valores de enumeração, portanto
MyEnum enumValue =MyEnum.values()[x];
Deveria trabalhar. É um pouco desagradável e pode ser melhor não tentar converter de ints para Enums (ou vice-versa), se possível.
Isso não é algo que geralmente é feito, então eu reconsideraria. Mas tendo dito isso, as operações fundamentais são: int -> enum usando EnumType.values () [intNum] e enum -> int usando enumInst.ordinal ().
No entanto, como qualquer implementação de values () não tem escolha a não ser fornecer uma cópia da matriz (as matrizes java nunca são somente leitura), você seria melhor atendido usando um EnumMap para armazenar em cache o mapeamento enum -> int.
Re "Isso geralmente não é feito": Caso comum em que é útil: enum corresponde aos valores int armazenados em um banco de dados.
precisa
@ToolmakerSteve, você está absolutamente certo de que os mapeamentos são necessários. Mas você gostaria de deixar esse tipo de codificação para algum mapeador OR ou algum kit de ferramentas / biblioteca?
Aqui está a solução que pretendo seguir. Isso não funciona apenas com números inteiros não sequenciais, mas também com qualquer outro tipo de dados que você queira usar como o ID subjacente para seus valores de enumeração.
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;}}
Eu só preciso converter IDs em enumerações em horários específicos (ao carregar dados de um arquivo), para que não haja motivo para manter o mapa na memória o tempo todo. Se você precisar que o mapa esteja acessível o tempo todo, sempre poderá armazená-lo em cache como membro estático da sua classe Enum.
IMHO, se eu estivesse preocupado com o uso de memória, criaria dinamicamente o @ossys do tipo HashMap, mas com código diferente quando o cache for nulo, em seguida, adicione um segundo método clearCachedValuesquando terminar de usá-lo (que define o campo privado novamente como nulo). Considero MyEnum.fromInt(i)mais fácil entender do que passar um objeto de mapa.
Com o padrão que você pode usar null, você pode throw IllegalArgumentExceptionou fromIntpode retornar um Optional, qualquer que seja o comportamento de sua preferência.
Você deve mencionar que está usando o Goiaba. Ou você pode usar fluxos:Map<Integer, MyEnum> reverseLookup = Arrays.stream(MyEnum.values()).collect(Collectors.toMap(MyEnum::getValue, Function.identity()));
shmosel 16/17
1
getValue()Também pode querer definir um método.
shmosel
@shmosel Ops, perdi a função getValue, obrigado. Digitar versões genéricas no fluxo de empilhamento nem sempre ocorre. Adicionado comentário sobre o uso do Guava com um link. Prefira o método Guava aos fluxos.
Chad Befus
4
Você pode iterar sobre values()enum e comparar o valor inteiro de enum com o dado idabaixo:
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}}
E use assim: TestEnum x = TestEnum.getEnum(4);//Will return TestEnum.Value4
espero que ajude;)
Uma boa opção é evitar a conversão de intpara enum: por exemplo, se você precisar do valor máximo, poderá comparar x.ordinal () com y.ordinal () e retornar x ou y correspondentemente. (Pode ser necessário reordenar os valores para tornar essa comparação significativa.)
Se isso não for possível, eu armazenaria MyEnum.values()em uma matriz estática.
Se você receber int de DB e quer convertê-lo em Enum, que eu acho que é uma tarefa muito comum, você vai precisar int -> conversão enum, IMO ..
Yuki Inoue
0
Essa é a mesma resposta que os médicos, mas mostra como eliminar o problema com matrizes mutáveis. Se você usar esse tipo de abordagem por causa da previsão de ramificação primeiro, terá muito pouco ou nenhum efeito e o código inteiro chamará apenas valores de matriz mutáveis () apenas uma vez. Como ambas as variáveis são estáticas, elas não consumirão n * memória para todos os usos dessa enumeração também.
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;}
Escreveu esta implementação. Permite valores ausentes, negativos e mantém o código consistente. O mapa também é armazenado em cache. Usa uma interface e precisa do Java 8.
Respostas:
Tente
MyEnum.values()[x]
ondex
deve estar0
ou1
, ou seja, um ordinal válido para essa enumeração.Note-se que em enums Java realmente são classes (e valores de enumeração são, portanto, objetos) e, portanto, você não pode lançar um
int
ou até mesmoInteger
para um ENUM.fonte
MyEnum.values()
como caro. ou seja, se você chamá-lo centenas de vezes.MyEnum.values()[x]
é uma operação cara. Se o desempenho for uma preocupação, convém fazer algo assim:fonte
MyEnum.values()[x]
uma operação cara? Não sei como funciona em detalhes, mas para mim parece que acessar um elemento em uma matriz não seria grande coisa, também conhecido como tempo constante. Se a matriz precisar ser compilada, leva-se tempo O (n), que é o mesmo tempo de execução da sua solução.values()
gera uma nova matriz de cada vez, porque as matrizes são mutáveis, portanto não seria seguro retornar o mesmo várias vezes. As instruções de switch não são necessariamente O (n), elas podem ser compiladas para saltar tabelas. Portanto, as alegações de Lorenzo parecem justificadas.myEnum = myEnumValues[i]
ainda retornará oi
th item no Enum sem alterações.Se você deseja fornecer valores inteiros, pode usar uma estrutura como a abaixo
fonte
Você pode tentar assim.
Criar classe com o ID do elemento.
Agora, busque esse Enum usando o id como int.
fonte
Coloco em cache os valores e crio um método simples de acesso estático:
fonte
values
o mesmo nome que o métodovalues()
. Eu usocachedValues
para o nome do campo.As enumerações Java não têm o mesmo tipo de mapeamento enum-para-int do C ++.
Dito isto, todas as enumerações têm um
values
método que retorna uma matriz de possíveis valores de enumeração, portantoDeveria trabalhar. É um pouco desagradável e pode ser melhor não tentar converter de
int
s paraEnum
s (ou vice-versa), se possível.fonte
Isso não é algo que geralmente é feito, então eu reconsideraria. Mas tendo dito isso, as operações fundamentais são: int -> enum usando EnumType.values () [intNum] e enum -> int usando enumInst.ordinal ().
No entanto, como qualquer implementação de values () não tem escolha a não ser fornecer uma cópia da matriz (as matrizes java nunca são somente leitura), você seria melhor atendido usando um EnumMap para armazenar em cache o mapeamento enum -> int.
fonte
Usar
MyEnum enumValue = MyEnum.values()[x];
fonte
Aqui está a solução que pretendo seguir. Isso não funciona apenas com números inteiros não sequenciais, mas também com qualquer outro tipo de dados que você queira usar como o ID subjacente para seus valores de enumeração.
Eu só preciso converter IDs em enumerações em horários específicos (ao carregar dados de um arquivo), para que não haja motivo para manter o mapa na memória o tempo todo. Se você precisar que o mapa esteja acessível o tempo todo, sempre poderá armazená-lo em cache como membro estático da sua classe Enum.
fonte
clearCachedValues
quando terminar de usá-lo (que define o campo privado novamente como nulo). ConsideroMyEnum.fromInt(i)
mais fácil entender do que passar um objeto de mapa.Caso ajude outras pessoas, a opção que eu prefiro, que não está listada aqui, usa a funcionalidade Mapas do Guava :
Com o padrão que você pode usar
null
, você podethrow IllegalArgumentException
oufromInt
pode retornar umOptional
, qualquer que seja o comportamento de sua preferência.fonte
Map<Integer, MyEnum> reverseLookup = Arrays.stream(MyEnum.values()).collect(Collectors.toMap(MyEnum::getValue, Function.identity()));
getValue()
Também pode querer definir um método.Você pode iterar sobre
values()
enum e comparar o valor inteiro de enum com o dadoid
abaixo:E use assim:
TestEnum x = TestEnum.getEnum(4);//Will return TestEnum.Value4
espero que ajude;)
fonte
Com base na resposta de @ChadBefus e no comentário @shmosel, eu recomendo usar isso. (Pesquisa eficiente e funciona em java puro> = 8)
fonte
Uma boa opção é evitar a conversão de
int
paraenum
: por exemplo, se você precisar do valor máximo, poderá comparar x.ordinal () com y.ordinal () e retornar x ou y correspondentemente. (Pode ser necessário reordenar os valores para tornar essa comparação significativa.)Se isso não for possível, eu armazenaria
MyEnum.values()
em uma matriz estática.fonte
Essa é a mesma resposta que os médicos, mas mostra como eliminar o problema com matrizes mutáveis. Se você usar esse tipo de abordagem por causa da previsão de ramificação primeiro, terá muito pouco ou nenhum efeito e o código inteiro chamará apenas valores de matriz mutáveis () apenas uma vez. Como ambas as variáveis são estáticas, elas não consumirão n * memória para todos os usos dessa enumeração também.
fonte
fonte
Em Kotlin:
Uso:
fonte
Escreveu esta implementação. Permite valores ausentes, negativos e mantém o código consistente. O mapa também é armazenado em cache. Usa uma interface e precisa do Java 8.
Enum
Interface
fonte