Spróbuj MyEnum.values()[x]gdzie xmusi być 0lub 1, tj. Prawidłowy porządek dla tego wyliczenia.
Zauważ, że w Javie wyliczenia są w rzeczywistości klasami (a wartości wyliczenia są zatem obiektami), a zatem nie można rzutować intani nawet Integerna wyliczenie.
+1: Możesz chcieć buforować, MyEnum.values()ponieważ jest drogi. tzn. jeśli nazwiesz to setki razy.
Peter Lawrey
6
@PeterLawrey Tylko dla kompletności, czy możesz wyjaśnić, dlaczego powinien być wolny? Nie widzę wyraźnego powodu.
Tarrasch
48
@Tarrasch, ponieważ tablice są zmienne, wartości () muszą zwracać kopię tablicy elementów na wypadek, gdybyś ją zmienił. Tworzenie tej kopii za każdym razem jest stosunkowo drogie.
Peter Lawrey,
9
@PeterLawrey Ostatnio używałem dużo haskell (gdzie wszystko jest niezmienne)! Dziękujemy za jasne i zwięzłe wyjaśnienie. :)
Tarrasch
jak zdobyć „x”?
Beeing Jk
161
MyEnum.values()[x]jest kosztowną operacją. Jeśli wydajność jest problemem, możesz chcieć zrobić coś takiego:
Jeśli chcesz uniknąć konserwacji przełącznika, skorzystaj z klasy using: private final MyEnum [] myEnumValues = MyEnum.values (); Następnie użycie: myEnum = myEnumValues [i];
Gili Nachum
23
@GiliNachum powiedział to w dziwny sposób, ale problemem z tym rozwiązaniem jest łatwość konserwacji. Jest to niezgodne z zasadą OSUSZANIA, co oznacza, że przy każdej zmianie wartości wyliczenia (zmiana kolejności, wartość (wartości) dodane, wartość (wartości) usunięte) instrukcja switch musi być jednocześnie aktualizowana. Komentarz Gili zmusza Javę do zachowania spójności z listą wartości wyliczeniowych, zmiany wartości wyliczeniowych w ogóle nie wpływają na to podejście.
Dandre Allison
3
@LorenzoPolidori, Czy możesz wyjaśnić, dlaczego uważasz MyEnum.values()[x]za kosztowną operację. Nie wiem, jak to działa w szczegółach, ale wydaje mi się, że dostęp do elementu w tablicy nie byłby niczym wielkim, czyli ciągłym czasem. Jeśli tablica musi zostać skompilowana, zajmuje to O (n) czas, co jest tym samym czasem uruchamiania, co rozwiązanie.
brunsgaard
1
@brunsgaard Zakładam, że values()generuje nową tablicę za każdym razem, ponieważ tablice są zmienne, więc wielokrotne zwracanie tego samego nie byłoby bezpieczne. Instrukcje przełączania niekoniecznie są O (n), można je skompilować, aby przejść do tabel. Więc twierdzenia Lorenza wydają się uzasadnione.
MikeFHay
1
Wersja @Johnson Gili nie wymaga żadnych dodatkowych zmian kodu poza zmianami w deklaracji Enum. Jeśli dodasz nowy element do wyliczenia, myEnum = myEnumValues[i]nadal zwróci ten ielement w wyliczeniu bez zmian.
Dandre Allison
45
Jeśli chcesz podać swoje liczby całkowite, możesz użyć struktury takiej jak poniżej
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, ponieważ podkreśla fakt, że wartości nie muszą być następujące po sobie.
rhavin
Ponadto wydaje się, że jest to jedyna odpowiedź, która działa, jeśli chcesz rzadki (lub powtarzany) zestaw wartości całkowitych zamiast używać domyślnych rzędnych od 0 .. (liczba-1). Może to być ważne, jeśli wchodzisz w interakcję z istniejącym kodem, na przykład przez sieć.
benkc
Warto zauważyć, że jak w powyższych odpowiedziach, buforowanie wyniku wartości () jest prawdopodobnie warte zachodu, aby uniknąć alokacji pamięci i tworzenia kopii zapasowych za każdym razem, gdy ją wywołujesz.
benkc
1
I, w zależności od długości twojego wyliczenia, możesz chcieć utworzyć HashMap lub użyć wyszukiwania binarnego lub czegoś takiego dla tego wyszukiwania, zamiast przeprowadzania wyszukiwania liniowego za każdym razem.
benkc
2
Powinien to być właściwy sposób i najlepsza praktyka konwersji int na wyliczanie i myślę, że można uprościć problem przez publiczne statyczne A GetValue (int _id) {for (A a: A.values () {if (a.getId ( ) == _ id) {return a;}} return null;} Pozbądź się rzeczy None, isEmpty () i porównaj ().
Chris.Zou
35
Możesz spróbować w ten sposób.
Utwórz klasę o identyfikatorze elementu.
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;}}
Z tego rozwiązania korzystam teraz. Ale IMHO jest mniej mylące, jeśli nie nadasz polu valuestej samej nazwy co metoda values(). Używam cachedValuesnazwy pola.
ToolmakerSteve
2
Wydajny i elegancki; skopiowane i wklejone do mojego projektu :) Jedyną rzeczą, którą zmieniłem, jest fromInt (int i), którą właśnie wywołałem z (int i), ponieważ jest trochę zbędne, aby mieć int dwa razy w podpisie.
pipedreambomb
1
dlaczego nie zainicjować od początku? po co czekać na pierwszy hit?
kaiser
9
Wyliczenia Java nie mają tego samego rodzaju odwzorowania wyliczania na int, co w C ++.
To powiedziawszy, wszystkie valueswyliczenia mają metodę, która zwraca tablicę możliwych wartości wyliczenia, więc
MyEnum enumValue =MyEnum.values()[x];
powinno działać. Jest to trochę nieprzyjemne i lepiej nie próbować konwertować z ints na Enums (lub odwrotnie), jeśli to możliwe.
To nie jest coś, co zwykle się robi, więc ponownie się zastanowię. Ale powiedziawszy to, podstawowymi operacjami są: int -> enum przy użyciu EnumType.values () [intNum] oraz enum -> int przy użyciu enumInst.ordinal ().
Ponieważ jednak jakakolwiek implementacja wartości () nie ma innego wyjścia, jak dać kopię tablicy (tablice java nigdy nie są tylko do odczytu), lepiej byłoby użyć EnumMap do buforowania odwzorowania enum -> int.
Odp: „To nie jest coś, co zwykle się robi”: częsty przypadek, w którym jest to przydatne: enum odpowiada wartościom int przechowywanym w bazie danych.
ToolmakerSteve
@ToolmakerSteve masz całkowitą rację, że mapowania są wymagane. Ale czy chcesz pozostawić tego rodzaju kodowanie jakiejś programowi odwzorowującemu OR lub zestawowi narzędzi / bibliotece?
Dilum Ranatunga,
7
Posługiwać się MyEnum enumValue = MyEnum.values()[x];
Oto rozwiązanie, z którym planuję pójść. Działa to nie tylko z niesekwencyjnymi liczbami całkowitymi, ale powinno współpracować z każdym innym typem danych, którego możesz chcieć użyć jako podstawowego identyfikatora dla swoich wartości wyliczeniowych.
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;}}
Muszę tylko przekonwertować id na wyliczenia w określonych momentach (podczas ładowania danych z pliku), więc nie mam powodu, aby zawsze przechowywać Mapę w pamięci. Jeśli potrzebujesz, aby mapa była zawsze dostępna, zawsze możesz buforować ją jako statyczny element klasy Enum.
IMHO, gdybym martwił się wykorzystaniem pamięci, dynamicznie tworzyłbym HashMap - jak @ossys, ale z innym kodem, gdy pamięć podręczna jest pusta, a następnie dodaje drugą metodę, clearCachedValuesgdy skończysz z niej korzystać (która ustawia prywatne pole z powrotem na null). Uważam, że MyEnum.fromInt(i)łatwiej to zrozumieć niż omijanie obiektu mapy.
ToolmakerSteve
6
W przypadku, gdy pomaga innym, preferowana przeze mnie opcja, która nie jest tutaj wymieniona, korzysta z funkcji Map Guava :
Powinieneś wspomnieć, że używasz Guawy. Lub możesz użyć strumieni:Map<Integer, MyEnum> reverseLookup = Arrays.stream(MyEnum.values()).collect(Collectors.toMap(MyEnum::getValue, Function.identity()));
shmosel
1
Może chcesz również zdefiniować getValue()metodę.
shmosel
@shmosel Ups, brakowało mi funkcji getValue, dzięki. Wpisywanie wersji ogólnych w stosie przepływu nie zawsze się sprawdza. Dodano komentarz na temat korzystania z Guava z linkiem. Preferuj metodę Guava od strumieni.
Czad Befus
4
Możesz iterować values()wyliczanie i porównywać wartość całkowitą wyliczenia z podanymi idjak poniżej:
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}}
I użyj tego w następujący sposób: TestEnum x = TestEnum.getEnum(4);//Will return TestEnum.Value4
mam nadzieję, że to pomoże;)
Dobrą opcją jest uniknięcie konwersji z intna enum: na przykład, jeśli potrzebujesz maksymalnej wartości, możesz porównać x.ordinal () z y.ordinal () i odpowiednio zwrócić x lub y. (Może być konieczne ponowne uporządkowanie wartości, aby takie porównanie miało sens).
Jeśli nie jest to możliwe, zapisałbym MyEnum.values()w tablicy statycznej.
Jeśli dostaniesz int z DB i chcesz przekonwertować go na Enum, co moim zdaniem jest bardzo częstym zadaniem, będziesz potrzebować int -> enum konwersji, IMO ..
Yuki Inoue
0
Jest to ta sama odpowiedź, co lekarze, ale pokazuje, jak wyeliminować problem ze zmiennymi tablicami. Jeśli zastosujesz takie podejście ze względu na przewidywanie gałęzi, jeśli będzie miało bardzo niewielki do zera efekt, a cały kod wywoła funkcję tablic zmiennych () tylko raz. Ponieważ obie zmienne są statyczne, nie będą zużywać pamięci n * dla każdego użycia tego wyliczenia.
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;}
Napisałem tę implementację. Pozwala to na brakujące wartości, wartości ujemne i utrzymuje spójność kodu. Mapa jest również buforowana. Korzysta z interfejsu i wymaga Java 8.
Odpowiedzi:
Spróbuj
MyEnum.values()[x]
gdziex
musi być0
lub1
, tj. Prawidłowy porządek dla tego wyliczenia.Zauważ, że w Javie wyliczenia są w rzeczywistości klasami (a wartości wyliczenia są zatem obiektami), a zatem nie można rzutować
int
ani nawetInteger
na wyliczenie.źródło
MyEnum.values()
ponieważ jest drogi. tzn. jeśli nazwiesz to setki razy.MyEnum.values()[x]
jest kosztowną operacją. Jeśli wydajność jest problemem, możesz chcieć zrobić coś takiego:źródło
MyEnum.values()[x]
za kosztowną operację. Nie wiem, jak to działa w szczegółach, ale wydaje mi się, że dostęp do elementu w tablicy nie byłby niczym wielkim, czyli ciągłym czasem. Jeśli tablica musi zostać skompilowana, zajmuje to O (n) czas, co jest tym samym czasem uruchamiania, co rozwiązanie.values()
generuje nową tablicę za każdym razem, ponieważ tablice są zmienne, więc wielokrotne zwracanie tego samego nie byłoby bezpieczne. Instrukcje przełączania niekoniecznie są O (n), można je skompilować, aby przejść do tabel. Więc twierdzenia Lorenza wydają się uzasadnione.myEnum = myEnumValues[i]
nadal zwróci teni
element w wyliczeniu bez zmian.Jeśli chcesz podać swoje liczby całkowite, możesz użyć struktury takiej jak poniżej
źródło
Możesz spróbować w ten sposób.
Utwórz klasę o identyfikatorze elementu.
Teraz pobierz to Enum używając id jako int.
źródło
Zapisuję wartości w pamięci podręcznej i tworzę prostą metodę dostępu statycznego:
źródło
values
tej samej nazwy co metodavalues()
. UżywamcachedValues
nazwy pola.Wyliczenia Java nie mają tego samego rodzaju odwzorowania wyliczania na int, co w C ++.
To powiedziawszy, wszystkie
values
wyliczenia mają metodę, która zwraca tablicę możliwych wartości wyliczenia, więcpowinno działać. Jest to trochę nieprzyjemne i lepiej nie próbować konwertować z
int
s naEnum
s (lub odwrotnie), jeśli to możliwe.źródło
To nie jest coś, co zwykle się robi, więc ponownie się zastanowię. Ale powiedziawszy to, podstawowymi operacjami są: int -> enum przy użyciu EnumType.values () [intNum] oraz enum -> int przy użyciu enumInst.ordinal ().
Ponieważ jednak jakakolwiek implementacja wartości () nie ma innego wyjścia, jak dać kopię tablicy (tablice java nigdy nie są tylko do odczytu), lepiej byłoby użyć EnumMap do buforowania odwzorowania enum -> int.
źródło
Posługiwać się
MyEnum enumValue = MyEnum.values()[x];
źródło
Oto rozwiązanie, z którym planuję pójść. Działa to nie tylko z niesekwencyjnymi liczbami całkowitymi, ale powinno współpracować z każdym innym typem danych, którego możesz chcieć użyć jako podstawowego identyfikatora dla swoich wartości wyliczeniowych.
Muszę tylko przekonwertować id na wyliczenia w określonych momentach (podczas ładowania danych z pliku), więc nie mam powodu, aby zawsze przechowywać Mapę w pamięci. Jeśli potrzebujesz, aby mapa była zawsze dostępna, zawsze możesz buforować ją jako statyczny element klasy Enum.
źródło
clearCachedValues
gdy skończysz z niej korzystać (która ustawia prywatne pole z powrotem na null). Uważam, żeMyEnum.fromInt(i)
łatwiej to zrozumieć niż omijanie obiektu mapy.W przypadku, gdy pomaga innym, preferowana przeze mnie opcja, która nie jest tutaj wymieniona, korzysta z funkcji Map Guava :
Z domyślnym można użyć
null
, możnathrow IllegalArgumentException
albo TwójfromInt
mogła zwracaćOptional
, co zachowanie wolisz.źródło
Map<Integer, MyEnum> reverseLookup = Arrays.stream(MyEnum.values()).collect(Collectors.toMap(MyEnum::getValue, Function.identity()));
getValue()
metodę.Możesz iterować
values()
wyliczanie i porównywać wartość całkowitą wyliczenia z podanymiid
jak poniżej:I użyj tego w następujący sposób:
TestEnum x = TestEnum.getEnum(4);//Will return TestEnum.Value4
mam nadzieję, że to pomoże;)
źródło
Opierając się na odpowiedzi @ChadBefus i komentarzu @shmosel, polecam użyć tego. (Skuteczne wyszukiwanie i działa na czystej Javie> = 8)
źródło
Dobrą opcją jest uniknięcie konwersji z
int
naenum
: na przykład, jeśli potrzebujesz maksymalnej wartości, możesz porównać x.ordinal () z y.ordinal () i odpowiednio zwrócić x lub y. (Może być konieczne ponowne uporządkowanie wartości, aby takie porównanie miało sens).Jeśli nie jest to możliwe, zapisałbym
MyEnum.values()
w tablicy statycznej.źródło
Jest to ta sama odpowiedź, co lekarze, ale pokazuje, jak wyeliminować problem ze zmiennymi tablicami. Jeśli zastosujesz takie podejście ze względu na przewidywanie gałęzi, jeśli będzie miało bardzo niewielki do zera efekt, a cały kod wywoła funkcję tablic zmiennych () tylko raz. Ponieważ obie zmienne są statyczne, nie będą zużywać pamięci n * dla każdego użycia tego wyliczenia.
źródło
źródło
W Kotlinie:
Stosowanie:
źródło
Napisałem tę implementację. Pozwala to na brakujące wartości, wartości ujemne i utrzymuje spójność kodu. Mapa jest również buforowana. Korzysta z interfejsu i wymaga Java 8.
Enum
Berło
źródło