Lookup Java enum dal valore stringa


1,504

Dire che ho un enum che è solo

public enum Blah { 
    A, B, C, D 
} 

e mi piacerebbe trovare il valore enum di una stringa, ad esempio "A" che sarebbe Blah.A. Come sarebbe possibile farlo?

È il Enum.valueOf() il metodo che mi serve? Se sì, come dovrei usare questo?

1,755

Sì, Blah.valueOf("A") ti darà Blah.A.

Si noti che il nome deve essere un esatto partita , con custodia: Blah.valueOf("a") e Blah.valueOf("A ") sia gettare un IllegalArgumentException.

I metodi statici valueOf() e values() vengono creati in fase di compilazione e non vengono visualizzati nel codice sorgente. Appaiono in Javadoc, però; ad esempio, Dialog.ModalityType mostra entrambi i metodi.

+68

Per riferimento, il metodo 'Blah.valueOf ("A") è' *** case sensitive *** e non tollera spazi estranei, quindi la soluzione alternativa proposta appresso con @ Josemi. 17 dic. 132013-12-17 17:37:05

+2

@ Michael Myers, Dal momento che questa risposta è la più votata di gran lunga, dovrei capire che è una buona pratica definire un enum e il suo valore di stringa essere esattamente lo stesso? 12 feb. 142014-02-12 21:24:44

+2

@KevinMeredith: Se intendi il valore 'toString()', no, non lo direi. 'name()' otterrà il nome effettivo definito della costante enum a meno che non lo si sovrascriva. 14 feb. 142014-02-14 04:10:45

+2

Cosa intendi esattamente per "sono stati creati in fase di compilazione e non compaiono nel codice sorgente". ? 07 mar. 142014-03-07 00:43:08

+6

@treesAreEverywhere Più precisamente, questi metodi sono _generated_ (o _synthesized_) dal compilatore. La definizione effettiva di 'enum Blah {...}' non dovrebbe provare a dichiarare i propri 'valori' né' valuesOf'. È come scrivere "AnyTypeName.class" anche se non hai mai dichiarato una variabile membro "class"; il compilatore rende tutto solo lavoro. (Questa risposta potrebbe non essere più utile per te 3 mesi più tardi, ma per ogni evenienza.) 30 mag. 142014-05-30 19:31:19

+1

Ottima risposta - in più ho trovato che aggiungere alcuni piccoli metodi di supporto all'enumerazione aiuta molto ... Ad esempio, se tu creare una mappa statica di voci minuscole nel costruttore, quindi è possibile aggiungere un metodo che osserva enum in modo insensibile alle maiuscole e minuscole o converte le barre trasversali in spazi in modo che l'input dell'utente come "Seconda voce" possa mappare a un enum SECOND_ENTRY. 19 nov. 152015-11-19 17:39:26

  0

Perché il commento di @ Brett ha così tanti voti? Ovviamente è case sensitive e non tollera spazi bianchi, tutto il resto sarebbe pazzo. 29 giu. 172017-06-29 08:54:03


65

Si dovrebbe anche fare attenzione con il tuo caso. Lasciatemi spiegare: l'esecuzione di Blah.valueOf("A") funziona, ma lo standard Blah.valueOf("a") non funzionerà. Quindi di nuovo Blah.valueOf("a".toUpperCase(Locale.ENGLISH)) funzionerebbe.

modificare
Modificato toUpperCase-toUpperCase(Locale.ENGLISH) base tc. comment e java docs

edit2 su Android si dovrebbe usare Locale.US, come sulai points out.

+6

Diffidare delle impostazioni locali predefinite! 28 nov. 122012-11-28 15:43:24

+3

Per voi utenti Android là fuori, vorrei sottolineare che [la documentazione di Android] (http://developer.android.com/reference/java/util/Locale.html#default_locale) incoraggia esplicitamente l'uso di 'Locale. US' per ingresso/uscita leggibile dalla macchina. 02 set. 132013-09-02 17:44:51

  0

Il maiuscolo è diverso in luoghi diversi? 14 ago. 142014-08-14 10:57:16

  0

@Trengot [Sì] (http://blog.codinghorror.com/whats-wrong-with-turkey/). 25 ago. 142014-08-25 11:26:22

+2

@Trengot Sì, sfortunatamente. La Turchia è un buon esempio. Combina questo con la gestione non corretta di Java dei set di caratteri predefiniti (predefinito su Latino su Windows invece che su Unicode) e scoprirai che è quasi sempre pericoloso usare le versioni predefinite dei metodi che accettano un set di caratteri o impostazioni locali. Dovresti quasi sempre definirli esplicitamente. 26 lug. 152015-07-26 13:34:22


27

Utilizzare Blah.valueOf(string) è meglio, ma è possibile utilizzare anche Enum.valueOf(Blah.class, string).

  0

Ehm, non hai notato che avevi già pubblicato essenzialmente la stessa risposta ... http://stackoverflow.com/questions/604424/java-enum-converting-string-to-enum/608156#608156 09 mag. 092009-05-09 17:47:18

  0

Um, no lascia che ti aggiusti. 10 mag. 092009-05-10 07:14:44

+1

Case sensitive, non aiuta! 28 giu. 152015-06-28 18:58:12

  0

@ MurtazaKanchwala Puoi chiarire il tuo commento? Cosa stai cercando di fare? 29 giu. 152015-06-29 10:18:25

+2

Ciao @PeterLawrey, mi è stato Tring per andare a prendere un Enum da una stringa enum pubblico ObjectType { \t \t persona ("persona") \t \t \t \t public String parameterName; \t \t \t \t ObjectType (String parameterName) { \t \t this.parameterName = parameterName; \t \t} \t \t public String getParameterName() { \t \t \t ritorno this.parameterName; \t \t} \t \t public static ObjectType fromstring (String parameterName) { \t \t \t se (parameterName! = Null) { \t \t \t \t per (ObjectType objType: ObjectType.values ​​()) { \t \t \t \t \t se (parameterName.equalsIgnoreCase (objType.parameterName)) { \t \t \t \t \t \t return objType; \t \t \t \t \t} \t \t \t \t} \t \t \t} \t \t \t ritorno nullo; \t \t} } 29 giu. 152015-06-29 17:45:51


93

Ecco un programma di utilità nifty che uso:

/** 
* A common method for all enums since they can't have another base class 
* @param <T> Enum type 
* @param c enum type. All enums must be all caps. 
* @param string case insensitive 
* @return corresponding enum, or null 
*/ 
public static <T extends Enum<T>> T getEnumFromString(Class<T> c, String string) { 
    if(c != null && string != null) { 
     try { 
      return Enum.valueOf(c, string.trim().toUpperCase()); 
     } catch(IllegalArgumentException ex) { 
     } 
    } 
    return null; 
} 

Poi nella mia classe enum solito ho questo per risparmiare un po 'di battitura:

public static MyEnum fromString(String name) { 
    return getEnumFromString(MyEnum.class, name); 
} 

Se le enumerazioni non sono tutti i tappi, basta cambiare il Linea Enum.valueOf.

Peccato che non sia possibile utilizzare T.class per Enum.valueOf come T come cancellato.

+149

Quel blocco vuoto di blocco mi fa davvero impazzire, mi dispiace. 31 lug. 102010-07-31 10:14:55

+24

@LazloBonin: le eccezioni sono per condizioni eccezionali, non per il flusso di controllo. Procurati una copia di [Effective Java] (http://java.sun.com/docs/books/effective/). 15 nov. 112011-11-15 17:09:06

+9

Se l'API Java che si desidera utilizzare genera un'eccezione e non si desidera che il codice ne generi una, è possibile ingoiare l'eccezione in questo modo o riscrivere la logica da zero in modo da non generare eccezioni in primo luogo . Inghiottire l'eccezione è spesso il male minore. 30 nov. 112011-11-30 19:26:55

+37

Orribile! Sempre, ** sempre ** cattura le eccezioni dove puoi gestirle. L'esempio sopra è un esempio perfetto ** come NON farlo **. Perché? Quindi restituisce NULL e il chiamante deve quindi verificare NULL o lanciare un NPE. Se il chiamante sa come gestire la situazione, allora un if se try-catch può sembrare un po 'più elegante, ** MA ** se non può gestire deve passare di nuovo nullo e il chiamante del chiamante ** di nuovo ** deve controllare NULL, ecc. ecc. 02 feb. 122012-02-02 07:52:31

+7

Per essere giusti alla soluzione sopra, ci sono davvero casi di utilizzo che richiedono di restituire null invece di lanciare IllegalArgumentException e interrompere il flusso del programma, ad esempio, mappando enum tra uno schema di servizio web e uno schema di database in cui non sono sempre uno a uno. Tuttavia, sono d'accordo sul fatto che il blocco catch non debba mai essere lasciato vuoto. Metti un po 'di codice come log.warn o qualcosa per scopo di monitoraggio. 06 feb. 122012-02-06 08:19:39

+1

Assolutamente! Registrare l'eccezione è una cosa sicura. Ma sono d'accordo con la deglutizione delle eccezioni. 17 mag. 122012-05-17 18:49:52

  0

Ora vorrei solo usare [Enum] di Guava (http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/base/Enums.html). Nota il diverso trattamento dell'input non valido: 'getIfPresent' restituisce' Optional.absent() ', che è quello che preferirei usare; mentre 'valueOfFunction(). apply()' restituisce 'null'. 20 ago. 122012-08-20 20:28:02

+1

I problemi iniziano quando si desidera scrivere un metodo statico che verifica se una stringa corrisponde a un'istanza di enum. L'unico modo per verificare i diversi valori enum è chiamare la funzione valueOf. Se lancia, il risultato è falso. 30 set. 122012-09-30 05:18:49

+4

Mi manca qualcosa? Qual è il valore aggiunto dei metodi sopra rispetto al semplice utilizzo di: 'MyEnum.valueOf (name)'? 12 feb. 132013-02-12 08:37:30

+2

@urig non fanno distinzione tra maiuscole e minuscole, a differenza di 'valueOf' 15 mag. 142014-05-15 19:49:57

+1

Se stai andando a scrivere una routine separata per il confronto senza distinzione tra maiuscole e minuscole, allora perché non * davvero * fai un controllo senza distinzione tra maiuscole e minuscole usando' String.equalsIgnoreCase' invece di questo 'toUpperCase' hardcoded? 26 lug. 152015-07-26 13:29:59

  0

Equivale a [EnumUtils di apache-common] (https://commons.apache.org/proper/commons-lang/javadocs/api-3.1/org/apache/commons/lang3/EnumUtils.html) metodo getEnum 22 ott. 152015-10-22 06:47:10

  0

@pjklauser No , Il metodo getEnum di EnumUtils fa * non * esegue la ricerca senza distinzione tra maiuscole e minuscole. 29 giu. 172017-06-29 08:51:45

  0

Mi piace questa utility. Abbiamo aggiunto un parametro "predefinito" nel caso in cui l'enumerazione non possa essere determinata: finale @Nullable T def 09 gen. 182018-01-09 18:59:27


671

Un'altra soluzione, se il testo non è lo stesso per il valore di enumerazione:

public enum Blah { 
    A("text1"), 
    B("text2"), 
    C("text3"), 
    D("text4"); 

    private String text; 

    Blah(String text) { 
    this.text = text; 
    } 

    public String getText() { 
    return this.text; 
    } 

    public static Blah fromString(String text) { 
    for (Blah b : Blah.values()) { 
     if (b.text.equalsIgnoreCase(text)) { 
     return b; 
     } 
    } 
    return null; 
    } 
} 
+315

'throw new IllegalArgumentException (" Nessuna costante con testo "+ testo +" trovato ")' sarebbe meglio di 'return null' . 31 lug. 102010-07-31 10:28:46

+5

@whiskeysierra Jon Skeet non sarebbe d'accordo. http://stackoverflow.com/questions/1167982/check-if-enum-exists-in-java 05 set. 112011-09-05 04:06:16

+9

@Sangdol Potrebbe * tu * illuminarci perché restituire null è meglio? 29 set. 112011-09-29 15:04:35

+2

Questo commento riguarda la risposta proposta di catturare effettivamente un'eccezione per determinare se la stringa rappresenta un valore enum valido. Probabilmente hai bisogno di un secondo metodo (ad esempio isValid) per tale caso d'uso. 29 set. 112011-09-29 21:44:01

+39

@Sangdol di solito è una buona cosa controllare cosa SUN - oops - Oracle sta facendo nella stessa situazione. E come [Enum.valueOf()] (http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Enum.html#valueOf) lo mostra ** IS ** best practice per lanciare un'eccezione in questo caso. * Perché * è una situazione eccezionale. "Ottimizzazione delle prestazioni" è una cattiva scusa per scrivere codice illeggibile ;-) 02 feb. 122012-02-02 07:43:58

+4

Bene, potresti anche usare l'annotazione @Nullable per renderla "leggibile" ;-) 03 feb. 122012-02-03 08:20:37

  0

Ok, per convertire una stringa in una costante enum, è probabilmente è buona norma lanciare un'eccezione in caso di corrispondenza nulle o nessuna, come fa valueOf. Tuttavia, pensa a come implementare un metodo per verificare se una stringa viene utilizzata dalle costanti enum ... esempio per aggirare tutto ciò all'indirizzo http://stackoverflow.com/a/12659023/744133 30 set. 122012-09-30 18:22:42

+1

Per quanto riguarda la gestione degli errori sempre dipende da dove provengono le informazioni. Se i tuoi valori provengono da una fonte esterna (input dell'utente ...) su cui non hai controllo, cattura l'errore e mostra un messaggio significativo se possibile. Nel caso in cui il valore passato a valueOf provenga dal tuo codice interno dovresti catturare gli errori e fallire (log e crash) probabilmente hai un bug e può essere risolto. 08 nov. 122012-11-08 10:29:12

  0

Ho una domanda davvero stupida ... nel tuo metodo fromString subito dopo dove esegui * equalsIgnoreCase * hai b.text. Il testo è un membro privato della classe enum come puoi accedervi? 24 mar. 132013-03-24 04:33:01

  0

@ Jan: Poiché il codice stesso si trova all'interno della classe enum e, naturalmente, ha visibilità su tutti gli attributi e i metodi di quella classe. 27 mar. 132013-03-27 06:16:18

+1

@raudi Preferisco null in questo caso, perché quando vado a ottenere il valore, trovo più pragmatico controllare "if (returnval == null)" che rilevare l'eccezione. Funziona anche idealisticamente troppo: ha più senso restituire un risultato vuoto se non corrisponde? o lanciare un errore? Penso che abbia più senso restituire un risultato vuoto. 24 mag. 132013-05-24 14:05:14

  0

@Tyzoid: Non ho detto che è sbagliato non ho nemmeno detto che è una cattiva pratica, ho appena detto che lanciare un'eccezione sembra più appropriato. Pensa a cosa deve fare il chiamante: se viene restituito un valore nullo, il valore restituito deve essere controllato dopo ogni chiamata, a meno che tu non voglia catturare NPE, cosa che non dovresti ;-). Ora guarda cosa succede se viene lanciata un'eccezione: il chiamante può decidere a quale livello vuole prenderlo: globalmente intercetta Eccezione, globale cattura l'Eccezione specifica o cattura l'Eccezione specifica per singole chiamate o qualsiasi combinazione di esse. Sicuramente molto più bello da usare ... 27 mag. 132013-05-27 17:05:33

+2

@Tyzoid @raudi Per essere onesti, specialmente se stai scrivendo il codice per durare e per gli altri, la cosa appropriata da fare è qualcosa di simile a ciò che l'interfaccia 'Queue' fa con' rimuovi 'vs.' poll' - hanno due versioni del metodo, una che restituisce 'null' su (un errore molto prevedibile e comune) e una che genera un'eccezione, quindi lascia che chi la sta usando decida cosa usare in base a che cosa richiede l'applicazione più ampia. 29 mag. 132013-05-29 21:45:55

+1

Suppongo che if (text == null) restituisca null; 'è migliore di' if (text! = Null) {....} restituisce null'. Il primo modo è più facile da capire. 01 ago. 132013-08-01 07:16:47

+1
  0

'text.equalsIgnoreCase (b.text)' può lanciare un'eccezione di puntatore nullo se null è passato a 'fromString() 'considerando che' b.text.equalsIgnoreCase (text) 'non lo farà (date le istanze enum elencate). 28 giu. 142014-06-28 01:12:18

  0

@Gus, per favore, leggi due righe prima di quella che dici che c'è un errore: 'if (text! = Null) {' ... 02 lug. 142014-07-02 05:50:03

+1

Scusa, ho scritto per digiunare ... Non è un errore. Il controllo nulla può essere evitato. Questo è proprio come "" pippo ".equals (barra)' invece di 'bar.equals (" pippo ")' 05 lug. 142014-07-05 13:26:02

  0

@ JoséMi Potrebbe anche essere una buona idea sovrascrivere il toString() predefinito e renderlo di ritorno 'testo' 03 ott. 142014-10-03 20:03:24

  0

L'aggiunta dei metodi 'text' field e' getText() 'non è necessaria in quanto il codice potrebbe altrettanto facilmente aver usato il metodo' name() 'generato automaticamente. È anche possibile scrivere un 'statico pubblico <E estende Enum <E>> com.mylibs.Enums.fromString (E enumType, String s)' che funzionerebbe per * qualsiasi * tipo Enum. 11 mag. 162016-05-11 16:46:21

+1

Un'alternativa in molti casi è di avere un valore SCONOSCI esplicito per l'enumerazione, in questo modo è possibile evitare i NPE ed essere ancora in grado di verificare la presenza di valori sconosciuti. 12 lug. 172017-07-12 21:57:16

  0

Per essere onesti con Jon Skeet, la domanda a cui stava rispondendo era come farlo senza lanciare e catturare un'eccezione. Il fatto che abbia risposto alla domanda come chiesto non significa che crede che sia una buona idea. @SanghyunLee 14 set. 172017-09-14 20:03:53


5
public static MyEnum getFromValue(String value) { 
    MyEnum resp = null; 
    MyEnum nodes[] = values(); 
    for(int i = 0; i < nodes.length; i++) { 
     if(nodes[i].value.equals(value)) { 
      resp = nodes[i]; 
      break; 
     } 
    } 
    return resp; 
} 
  0

dai un'occhiata a questo link per le guide su come rispondere e fare domande su stackoverflow.com: http://stackoverflow.com/faq 09 nov. 112011-11-09 18:15:06

+1

Questo è più o meno lo stesso della risposta di JoséMi 14 nov. 112011-11-14 12:40:14


11

Un altro modo di fare questo usando metodo statico implicita name() di Enum.Nome restituirà la stringa esatto utilizzato per creare quella enum che può essere utilizzato per controllare contro la condizione stringa:

public enum Blah { 

    A, B, C, D; 

    public static Blah getEnum(String s){ 
     if(A.name().equals(s)){ 
      return A; 
     }else if(B.name().equals(s)){ 
      return B; 
     }else if(C.name().equals(s)){ 
      return C; 
     }else if (D.name().equals(s)){ 
      return D; 
     } 
     throw new IllegalArgumentException("No Enum specified for this string"); 
    } 
} 

Testing:

System.out.println(Blah.getEnum("B").name());

//it will print B B 

ispirazione: 10 Examples of Enum in Java

+7

Questo è essenzialmente ciò che 'valueOf' fa per te. Questo metodo statico non offre nulla in più, eccezione e tutto. Quindi i costrutti if/else sono molto pericolosi ... ogni nuova costante enum causerà l'interruzione di questo metodo senza modifiche. 30 set. 122012-09-30 18:01:39

  0

Considera anche questo esempio di come possiamo usare valueOf per fare una ricerca insensibile al caso, o come possiamo evitare la sua eccezione e impiegare alias per fornire nomi alternativi: http://stackoverflow.com/a/12659023/744133 30 set. 122012-09-30 18:18:33

+1

'nome () 'non è statico. 21 apr. 142014-04-21 00:39:07


34

Ecco un metodo che può farlo per qualsiasi Enum ed è insensibile al maiuscolo/minuscolo.

/** 
* Finds the value of the given enumeration by name, case-insensitive. 
* Throws an IllegalArgumentException if no match is found. 
**/ 
public static <T extends Enum<T>> T valueOfIgnoreCase(
     Class<T> enumeration, String name) { 

    for (T enumValue : enumeration.getEnumConstants()) { 
     if (enumValue.name().equalsIgnoreCase(name)) { 
      return enumValue; 
     } 
    } 

    throw new IllegalArgumentException(String.format(
     "There is no value with name '%s' in Enum %s", 
     name, enumeration.getName() 
    )); 
} 
  0

Questa variante sta funzionando correttamente: 'equalsIgnoreCase' è la strada da percorrere. +1 26 lug. 152015-07-26 13:35:57


21

Se non si vuole scrivere la propria utilità usa biblioteca di Google:

Enums.getIfPresent(Blah.class, "A") 

A differenza del costruito in funzione java che ti permette di controllare se una è presente in Blah e non lo fa lanciare un'eccezione

+2

parte triste è, questo restituisce un google opzionale e non java opzionale 19 ago. 162016-08-19 00:02:58


6

Soluzione che utilizza le librerie Guava. Il metodo getPlanet() non fa distinzione tra maiuscole e minuscole, quindi getPlanet ("MerCUrY") restituirà Planet.MERCURY.

package com.universe.solarsystem.planets; 
import org.apache.commons.lang3.StringUtils; 
import com.google.common.base.Enums; 
import com.google.common.base.Optional; 

//Pluto and Eris are dwarf planets, who cares! 
public enum Planet { 
    MERCURY, 
    VENUS, 
    EARTH, 
    MARS, 
    JUPITER, 
    SATURN, 
    URANUS, 
    NEPTUNE; 

    public static Planet getPlanet(String name) { 
     String val = StringUtils.trimToEmpty(name).toUpperCase(); 
     Optional <Planet> possible = Enums.getIfPresent(Planet.class, val); 
     if (!possible.isPresent()) { 
     throw new IllegalArgumentException(val + "? There is no such planet!"); 
     } 
     return possible.get(); 
    } 
} 

6

da aggiungere alle risposte precedenti, e affrontare alcune delle discussioni intorno a valori nulli e NPE che sto usando Guava Optional per gestire assenti casi/non valide. Funziona perfettamente per l'analisi di parametri URI/parametri.

public enum E { 
    A,B,C; 
    public static Optional<E> fromString(String s) { 
     try { 
      return Optional.of(E.valueOf(s.toUpperCase())); 
     } catch (IllegalArgumentException|NullPointerException e) { 
      return Optional.absent(); 
     } 
    } 
} 

Per chi non sa, ecco qualche informazione in più su come evitare nulla con Optional: https://code.google.com/p/guava-libraries/wiki/UsingAndAvoidingNullExplained#Optional


3

java.lang.Enum definisce diversi metodi utili, che è disponibile per tutti i tipi di censimento nel Java:

  • È utilizzare il metodo name() per ottenere il nome di qualsiasi costante Enum. Il letterale stringa usato per scrivere le costanti enum è il loro nome.
  • Analogamente il metodo values() può essere utilizzato per ottenere una matrice di tutte le costanti Enum da un tipo Enum.
  • E per la domanda posta, è possibile utilizzare il metodo valueOf() per convertire qualsiasi stringa su costante Enum in Java, come illustrato di seguito.
public class EnumDemo06 { 
    public static void main(String args[]) { 
     Gender fromString = Gender.valueOf("MALE"); 
     System.out.println("Gender.MALE.name() : " + fromString.name()); 
    } 

    private enum Gender { 
     MALE, FEMALE; 
    } 
} 

Output: 
Gender.MALE.name() : MALE 

In questo frammento di codice, valueOf() metodo restituisce una costante Gender.MALE Enum, chiamando il nome su quel restituisce "MALE".


13

Potrebbe essere necessario questo:

public enum ObjectType { 
    PERSON("Person"); 

    public String parameterName; 

    ObjectType(String parameterName) { 
     this.parameterName = parameterName; 
    } 

    public String getParameterName() { 
     return this.parameterName; 
    } 

    //From String method will return you the Enum for the provided input string 
    public static ObjectType fromString(String parameterName) { 
     if (parameterName != null) { 
      for (ObjectType objType : ObjectType.values()) { 
       if (parameterName.equalsIgnoreCase(objType.parameterName)) { 
        return objType; 
       } 
      } 
     } 
     return null; 
    } 
} 

One More Aggiunta:

public static String fromEnumName(String parameterName) { 
     if (parameterName != null) { 
      for (DQJ objType : DQJ.values()) { 
       if (parameterName.equalsIgnoreCase(objType.name())) { 
        return objType.parameterName; 
       } 
      } 
     } 
     return null; 
    } 

Questo lo restituisca il valore con un nome stringata Enum Per esempio se fornisci "PERSON" in fromEnumName, ti restituirà il valore di Enum i.e. "Persona"


4

O (1) metodo ispirato al codice generato dal risparmio che utilizza una hashmap.biblioteca

public enum USER { 
     STUDENT("jon",0),TEACHER("tom",1); 

     private static final Map<String, Integer> map = new HashMap<>(); 

     static { 
       for (USER user : EnumSet.allOf(USER.class)) { 
         map.put(user.getTypeName(), user.getIndex()); 
       } 
     } 

     public static int findIndexByTypeName(String typeName) { 
       return map.get(typeName); 
     } 

     private USER(String typeName,int index){ 
       this.typeName = typeName; 
       this.index = index; 
     } 
     private String typeName; 
     private int index; 
     public String getTypeName() { 
       return typeName; 
     } 
     public void setTypeName(String typeName) { 
       this.typeName = typeName; 
     } 
     public int getIndex() { 
       return index; 
     } 
     public void setIndex(int index) { 
       this.index = index; 
     } 

} 

2

di Apache commons-lang ha una funzione statica org.apache.commons.lang3.EnumUtils.getEnum che mappare una stringa al vostro tipo Enum. La stessa risposta essenzialmente come Geoffreys, ma perché tira il tuo quando è già in circolazione.


1

Un'altra utilità che cattura in modo inverso. Usando un valore che identifica Enum, non dal suo nome.

import java.lang.reflect.Method; 
import java.lang.reflect.Modifier; 
import java.util.EnumSet; 

public class EnumUtil { 

    /** 
    * Returns the <code>Enum</code> of type <code>enumType</code> whose a 
    * public method return value of this Enum is 
    * equal to <code>valor</code>.<br/> 
    * Such method should be unique public, not final and static method 
    * declared in Enum. 
    * In case of more than one method in match those conditions 
    * its first one will be chosen. 
    * 
    * @param enumType 
    * @param value 
    * @return 
    */ 
    public static <E extends Enum<E>> E from(Class<E> enumType, Object value) { 
     String methodName = getMethodIdentifier(enumType); 
     return from(enumType, value, methodName); 
    } 

    /** 
    * Returns the <code>Enum</code> of type <code>enumType</code> whose 
    * public method <code>methodName</code> return is 
    * equal to <code>value</code>.<br/> 
    * 
    * @param enumType 
    * @param value 
    * @param methodName 
    * @return 
    */ 
    public static <E extends Enum<E>> E from(Class<E> enumType, Object value, String methodName) { 
     EnumSet<E> enumSet = EnumSet.allOf(enumType); 
     for (E en : enumSet) { 
      try { 
       String invoke = enumType.getMethod(methodName).invoke(en).toString(); 
       if (invoke.equals(value.toString())) { 
        return en; 
       } 
      } catch (Exception e) { 
       return null; 
      } 
     } 
     return null; 
    } 

    private static String getMethodIdentifier(Class<?> enumType) { 
     Method[] methods = enumType.getDeclaredMethods(); 
     String name = null; 
     for (Method method : methods) { 
      int mod = method.getModifiers(); 
      if (Modifier.isPublic(mod) && !Modifier.isStatic(mod) && !Modifier.isFinal(mod)) { 
       name = method.getName(); 
       break; 
      } 
     } 
     return name; 
    } 
} 

Esempio:

public enum Foo { 
    ONE("eins"), TWO("zwei"), THREE("drei"); 

    private String value; 

    private Foo(String value) { 
     this.value = value; 
    } 

    public String getValue() { 
     return value; 
    } 
} 

EnumUtil.from(Foo.class, "drei") rendimenti Foo.THREE, perché userà getValue per corrispondenza "Drei", che è pubblico unico, non definitiva e metodo statico non in Foo. Nel caso in cui Foo abbia più di un metodo pubblico, non finale e non statico, ad esempio, getTranslate che restituisce "drei", è possibile utilizzare l'altro metodo: EnumUtil.from(Foo.class, "drei", "getTranslate").


29

Usare il modello da Joshua Bloch, Effective Java:

(semplificato per brevità)

enum MyEnum { 
    ENUM_1("A"), 
    ENUM_2("B"); 

    private String name; 

    private static final Map<String,MyEnum> ENUM_MAP; 

    MyEnum (String name) { 
    this.name = name; 
    } 

    public String getName() { 
    return this.name; 
    } 

    // Build an immutable map of String name to enum pairs. 
    // Any Map impl can be used. 

    static { 
    Map<String,MyEnum> map = new ConcurrentHashMap<String,MyEnum>(); 
    for (MyEnum instance : MyEnum.values()) { 
     map.put(instance.getName(),instance); 
    } 
    ENUM_MAP = Collections.unmodifiableMap(map); 
    } 

    public static MyEnum get (String name) { 
    return ENUM_MAP.get(name); 
    } 
} 

Vedi anche:

Oracle Java Example using Enum and Map of instances

Execution order of of static blocks in an Enum type

How can I lookup a Java enum from its String value

+1

se Joshua Bloch ha detto che quindi questa è l'unica strada da percorrere :-). È un peccato che devo sempre scorrere qui. 10 gen. 172017-01-10 09:51:41

+2

Questo è ancora più semplice in Java 8 come puoi fare: 'Stream.of (MyEnum.values ​​()). Collect (toMap (Enum :: name, identity()))' Raccomando anche di sovrascrivere toString() (passato in attraverso il costruttore) e usando quello invece del nome, specialmente se l'Enum è associato a dati serializzabili in quanto ciò consente di controllare l'involucro senza dare a Sonar un adattamento. 27 apr. 172017-04-27 17:01:13

+1

Java 8 sicuramente può/cambierà molte (migliori) risposte su questo forum. Non sono sicuro di aver mai avuto la coda (Sonar) per il cane (codice dell'applicazione). 28 apr. 172017-04-28 20:31:57

  0

Se hai intenzione di metterlo in un 'unmodifiableMap' in ogni caso, quindi non vi è alcun vantaggio per iniziare con un' ConcurrentHashMap'. Basta usare un 'HashMap'. (Se hai "ImmutableMap" di Guava, ti consiglio invece!) 08 mar. 182018-03-08 16:13:53

  0

ImmutableMap di Google è sicuramente una migliore (vera immutabile) implementazione ma allo scopo di dimostrare una soluzione solo-core-Java ... e concentrarsi sul Caso di ricerca delle stringhe, sono state utilizzate solo classi core-Java. In generale, è stato rilevato che ConcurrentHashMap è quasi sempre preferito su HashMap dato il profilo generale delle prestazioni (aggiungi, rimuovi, modifica) e la semplicità rispetto al wrapping/locking di HashMap quando è necessario prendere in considerazione la modifica simultanea. 09 mar. 182018-03-09 16:47:16


0

Mi piace utilizzare questo tipo di processo per analizzare i comandi come stringhe nelle enumerazioni. Di solito ho una delle enumerazioni come "sconosciuta", quindi aiuta ad avere quella restituita quando gli altri non vengono trovati (anche su una base insensibile alle maiuscole e minuscole) piuttosto che null (che significa che non c'è alcun valore). Quindi io uso questo approccio.

static <E extends Enum<E>> Enum getEnumValue(String what, Class<E> enumClass) { 
    Enum<E> unknown=null; 
    for (Enum<E> enumVal: enumClass.getEnumConstants()) { 
     if (what.compareToIgnoreCase(enumVal.name()) == 0) { 
      return enumVal; 
     } 
     if (enumVal.name().compareToIgnoreCase("unknown") == 0) { 
      unknown=enumVal; 
     } 
    } 
    return unknown; 
} 
  0

Sembra buono, ma essenzialmente uguale alla risposta di Patrick Arnesen ... 15 nov. 162016-11-15 01:49:05


1

Aggiunta al top rated risposta, con un programma di utilità utile ...

valueOf() tiri due eccezioni differenti nei casi in cui non gli piace il suo input.

  • IllegalArgumentException
  • NullPointerExeption

Se i requisiti sono tali che non si ha alcuna garanzia che il vostro String sarà sicuramente corrispondere un valore di enumerazione, ad esempio, se i dati String viene da un database e potrebbe contenere la vecchia versione dell'enumerazione, quindi dovrai gestirli spesso ...

Quindi ecco un metodo riutilizzabile che ho scritto che ci consente di definire un Enum predefinito da restituire se la stringa che passiamo non fa t incontro.

private static <T extends Enum<T>> T valueOf(String name , T defaultVal) { 
     try { 
      return Enum.valueOf(defaultVal.getDeclaringClass() , name); 
     } catch (IllegalArgumentException | NullPointerException e) { 
      return defaultVal; 
     } 
    } 

usare in questo modo:

public enum MYTHINGS { 
    THINGONE, 
    THINGTWO 
} 

public static void main(String [] asd) { 
    valueOf("THINGTWO" , MYTHINGS.THINGONE);//returns MYTHINGS.THINGTWO 
    valueOf("THINGZERO" , MYTHINGS.THINGONE);//returns MYTHINGS.THINGONE 
} 

3

In Java 8 il modello di mappa statica è ancora più facile ed è il mio metodo preferito per il tuo. Se si desidera utilizzare l'Enum con Jackson è possibile ignorare toString e l'uso che, invece di nome, quindi annotare con @JsonValue

public enum MyEnum { 
    BAR, 
    BAZ; 
    private static final Map<String, MyEnum> MAP = Stream.of(MyEnum.values()).collect(Collectors.toMap(Enum::name, Function.identity())); 
    public static MyEnum fromName(String name){ 
     return MAP.get(name); 
    } 
} 

public enum MyEnumForJson { 
    BAR("bar"), 
    BAZ("baz"); 
    private static final Map<String, MyEnumForJson> MAP = Stream.of(MyEnumForJson.values()).collect(Collectors.toMap(Object::toString, Function.identity())); 
    private final String value; 

    MyEnumForJson(String value) { 
     this.value = value; 
    } 

    @JsonValue 
    @Override 
    public String toString() { 
     return value; 
    } 

    public static MyEnumForJson fromValue(String value){ 
     return MAP.get(value); 
    } 
} 

5

I miei 2 centesimi qui: usando Java8 Streams + il controllo di uno stringa esatta:

public enum MyEnum { 
    VALUE_1("Super"), 
    VALUE_2("Rainbow"), 
    VALUE_3("Dash"), 
    VALUE_3("Rocks"); 

    private final String value; 

    MyEnum(String value) { 
     this.value = value; 
    } 

    /** 
    * @return the Enum representation for the given string. 
    * @throws IllegalArgumentException if unknown string. 
    */ 
    public static MyEnum asEnumValue(String s) throws IllegalArgumentException { 
     return Arrays.stream(MyEnum.values()) 
       .filter(v -> v.value.equals(s)) 
       .findFirst(); 
       .orElseThrow(() -> new IllegalArgumentException("unknown value: " + s)); 
    } 
} 

4

In Java 8:

public enum Blah 
{ 
    A("text1"), 
    B("text2"), 
    C("text3"), 
    D("text4"); 

    private String text; 

    Blah(String text) { 
     this.text = text; 
    } 

    public String getText() { 
     return this.text; 
    } 

    public static Blah fromText(String text) { 
     return Arrays.stream(values()) 
      .filter(bl -> bl.text.equalsIgnoreCase(text)) 
      .findFirst() 
      .orElse(null); 
    } 
} 
  0

esattamente quello di cui ho bisogno 17 nov. 172017-11-17 10:53:00


0

Che dire?

public enum MyEnum { 
    FIRST, 
    SECOND, 
    THIRD; 

    public static Optional<MyEnum> fromString(String value){ 
     try{ 
      return Optional.of(MyEnum.valueOf(value)); 
     }catch(Exception e){ 
      return Optional.empty(); 
     } 
    } 
}