Recherche enum Java par valeur de chaîne

Dis que j’ai un enum qui est juste

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

et je voudrais trouver la valeur enum d’une chaîne, par exemple "A" qui serait Blah.A Comment serait-il possible de faire cela?

Est-ce que Enum.valueOf() la méthode dont j’ai besoin? Si oui, comment l’utiliser?

Oui, Blah.valueOf("A") vous donnera Blah.A

Notez que le nom doit correspondre exactement , y compris la casse: Blah.valueOf("a") et Blah.valueOf("A ") jettent tous deux une IllegalArgumentException .

Les méthodes statiques valueOf() et values() sont créées au moment de la compilation et n’apparaissent pas dans le code source. Ils apparaissent dans Javadoc, cependant; Par exemple, Dialog.ModalityType affiche les deux méthodes.

Une autre solution si le texte n’est pas identique à la valeur d’énumération:

 public enum Blah { A("text1"), B("text2"), C("text3"), D("text4"); private Ssortingng text; Blah(Ssortingng text) { this.text = text; } public Ssortingng getText() { return this.text; } public static Blah fromSsortingng(Ssortingng text) { for (Blah b : Blah.values()) { if (b.text.equalsIgnoreCase(text)) { return b; } } return null; } } 

Voici un utilitaire astucieux que j’utilise:

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

Ensuite, dans ma classe d’énumération, j’ai l’habitude de sauvegarder ceci:

 public static MyEnum fromSsortingng(Ssortingng name) { return getEnumFromSsortingng(MyEnum.class, name); } 

Si vos énumérations ne sont pas toutes en majuscules, modifiez simplement la ligne Enum.valueOf .

Dommage que je ne puisse pas utiliser T.class pour Enum.valueOf car T est effacé.

Vous devriez également faire attention à votre cas. Laissez-moi vous expliquer: faire Blah.valueOf("A") fonctionne, mais Blah.valueOf("a") ne fonctionnera pas. Ensuite, Blah.valueOf("a".toUpperCase(Locale.ENGLISH)) fonctionnerait.

modifier
Changement de toUpperCase à toUpperCase(Locale.ENGLISH) basé sur tc. commentaire et les documents java

edit2 Sur Android, vous devriez utiliser Locale.US , comme le souligne Sulai .

Utilisez le motif de Joshua Bloch, Effective Java :

(simplifié pour des raisons de concision)

 enum MyEnum { ENUM_1("A"), ENUM_2("B"); private Ssortingng name; private static final Map ENUM_MAP; MyEnum (Ssortingng name) { this.name = name; } public Ssortingng getName() { return this.name; } // Build an immutable map of Ssortingng name to enum pairs. // Any Map impl can be used. static { Map map = new ConcurrentHashMap(); for (MyEnum instance : MyEnum.values()) { map.put(instance.getName(),instance); } ENUM_MAP = Collections.unmodifiableMap(map); } public static MyEnum get (Ssortingng name) { return ENUM_MAP.get(name); } } 

Regarde aussi:

Exemple Oracle Java utilisant Enum et Map of instances

Ordre d’exécution des blocs statiques dans un type Enum

Comment puis-je rechercher un enum Java à partir de sa valeur de chaîne

Voici une méthode qui peut le faire pour n’importe quel Enum et qui est insensible à la casse.

 /** * Finds the value of the given enumeration by name, case-insensitive. * Throws an IllegalArgumentException if no match is found. **/ public static > T valueOfIgnoreCase( Class enumeration, Ssortingng name) { for (T enumValue : enumeration.getEnumConstants()) { if (enumValue.name().equalsIgnoreCase(name)) { return enumValue; } } throw new IllegalArgumentException(Ssortingng.format( "There is no value with name '%s' in Enum %s", name, enumeration.getName() )); } 

Utiliser Blah.valueOf(ssortingng) est le meilleur mais vous pouvez aussi utiliser Enum.valueOf(Blah.class, ssortingng) .

Si vous ne voulez pas écrire votre propre utilitaire, utilisez la bibliothèque de goyave de Google:

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

Contrairement à la fonction Java intégrée, il vous permet de vérifier si A est présent dans Blah et ne lance pas d’exception.

Vous pourriez avoir besoin de ceci:

 public enum ObjectType { PERSON("Person"); public Ssortingng parameterName; ObjectType(Ssortingng parameterName) { this.parameterName = parameterName; } public Ssortingng getParameterName() { return this.parameterName; } //From Ssortingng method will return you the Enum for the provided input ssortingng public static ObjectType fromSsortingng(Ssortingng parameterName) { if (parameterName != null) { for (ObjectType objType : ObjectType.values()) { if (parameterName.equalsIgnoreCase(objType.parameterName)) { return objType; } } } return null; } } 

Un plus:

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

Cela vous renverra la valeur par un Nom Enum Ssortingngifié Par exemple si vous fournissez “PERSON” dans fromEnumName, cela vous renverra la valeur de Enum ie “Personne”

Dans Java 8 ou version ultérieure, à l’aide de Streams :

 public enum Blah { A("text1"), B("text2"), C("text3"), D("text4"); private Ssortingng text; Blah(Ssortingng text) { this.text = text; } public Ssortingng getText() { return this.text; } public static Blah fromText(Ssortingng text) { return Arrays.stream(values()) .filter(bl -> bl.text.equalsIgnoreCase(text)) .findFirst() .orElse(null); } } 

Une autre façon de le faire en utilisant un name() méthode statique implicite name() de Enum. name renverra la chaîne exacte utilisée pour créer cette énumération qui peut être utilisée pour vérifier la chaîne fournie:

 public enum Blah { A, B, C, D; public static Blah getEnum(Ssortingng 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 ssortingng"); } } 

Essai:

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

 //it will print BB 

inspiration: 10 exemples de Enum en Java

Mes 2 cents ici: utiliser Java8 Streams + vérifier une chaîne exacte:

 public enum MyEnum { VALUE_1("Super"), VALUE_2("Rainbow"), VALUE_3("Dash"), VALUE_3("Rocks"); private final Ssortingng value; MyEnum(Ssortingng value) { this.value = value; } /** * @return the Enum representation for the given ssortingng. * @throws IllegalArgumentException if unknown ssortingng. */ public static MyEnum fromSsortingng(Ssortingng s) throws IllegalArgumentException { return Arrays.stream(MyEnum.values()) .filter(v -> v.value.equals(s)) .findFirst() .orElseThrow(() -> new IllegalArgumentException("unknown value: " + s)); } } 

** MODIFIER **

Renommé la fonction en fromSsortingng() depuis son nom en utilisant cette convention, vous obtiendrez certains avantages du langage Java lui-même; par exemple:

  1. Conversion directe des types à l’annotation HeaderParam

Solution utilisant les bibliothèques de goyave. La méthode getPlanet () est insensible à la casse, donc getPlanet (“MerCUrY”) renverra Planet.MERCURY.

 package com.universe.solarsystem.planets; import org.apache.commons.lang3.SsortingngUtils; 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(Ssortingng name) { Ssortingng val = SsortingngUtils.sortingmToEmpty(name).toUpperCase(); Optional  possible = Enums.getIfPresent(Planet.class, val); if (!possible.isPresent()) { throw new IllegalArgumentException(val + "? There is no such planet!"); } return possible.get(); } } 

Pour append aux réponses précédentes, et aborder certaines des discussions autour des valeurs NULL et NPE, j’utilise les options Guava pour gérer les observations absentes / non valides. Cela fonctionne très bien pour l’parsing des URI / parameters.

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

Pour ceux qui ne sont pas au courant, voici quelques informations supplémentaires sur la manière d’éviter les null avec les options: https://code.google.com/p/guava-libraries/wiki/UsingAndAvoidingNullExplained#Optional

 public static MyEnum getFromValue(Ssortingng 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; } 

O (1) méthode inspirée du code généré par l’épargne qui utilise un hashmap.

 public enum USER { STUDENT("jon",0),TEACHER("tom",1); private static final Map 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; } } 

Dans Java 8, le modèle de carte statique est encore plus simple et constitue ma méthode préférée. Si vous voulez utiliser Enum avec Jackson, vous pouvez remplacer toSsortingng et l’utiliser plutôt que name, puis annoter avec @JsonValue

 public enum MyEnum { BAR, BAZ; private static final Map MAP = Stream.of(MyEnum.values()).collect(Collectors.toMap(Enum::name, Function.identity())); public static MyEnum fromName(Ssortingng name){ return MAP.get(name); } } public enum MyEnumForJson { BAR("bar"), BAZ("baz"); private static final Map MAP = Stream.of(MyEnumForJson.values()).collect(Collectors.toMap(Object::toSsortingng, Function.identity())); private final Ssortingng value; MyEnumForJson(Ssortingng value) { this.value = value; } @JsonValue @Override public Ssortingng toSsortingng() { return value; } public static MyEnumForJson fromValue(Ssortingng value){ return MAP.get(value); } } 

java.lang.Enum définit plusieurs méthodes utiles, disponibles pour tous les types d’énumération Java:

  • Vous pouvez utiliser la méthode name() pour obtenir le nom de toutes les constantes Enum. Le littéral de chaîne utilisé pour écrire des constantes enum est leur nom.
  • De même values() méthode values() peut être utilisée pour obtenir un tableau de toutes les constantes Enum d’un type Enum.
  • Et pour la question posée, vous pouvez utiliser la méthode valueOf() pour convertir n’importe quelle chaîne en constante Enum en Java, comme indiqué ci-dessous.
 public class EnumDemo06 { public static void main(Ssortingng args[]) { Gender fromSsortingng = Gender.valueOf("MALE"); System.out.println("Gender.MALE.name() : " + fromSsortingng.name()); } private enum Gender { MALE, FEMALE; } } Output: Gender.MALE.name() : MALE 

Dans cet extrait de code, la méthode valueOf() renvoie une constante Enum Gender.MALE, appelant le nom qui renvoie "MALE" .

La bibliothèque commons-lang d’ Apache possède une fonction statique org.apache.commons.lang3.EnumUtils.getEnum qui mappera une chaîne à votre type Enum. Même réponse que Geoffreys mais pourquoi rouler vous-même quand il est déjà dans la nature.

Ajout de la réponse la mieux notée, avec un utilitaire utile …

valueOf() lance deux exceptions différentes dans les cas où il n’aime pas ses entrées.

  • IllegalArgumentException
  • NullPointerExeption

Si vos exigences sont telles que vous n’avez aucune garantie que votre chaîne correspondra à une valeur enum, par exemple si les données Ssortingng proviennent d’une firebase database et peuvent contenir une ancienne version de l’énum, ​​vous devrez alors les gérer. souvent…

Donc, voici une méthode réutilisable que j’ai écrite et qui nous permet de définir un Enum par défaut à retourner si la chaîne que nous réussissons ne correspond pas.

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

Utilisez-le comme ceci:

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

Un autre utilitaire de capture en sens inverse. En utilisant une valeur qui identifie cette Enum, pas de son nom.

 import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.EnumSet; public class EnumUtil { /** * Returns the Enum of type enumType whose a * public method return value of this Enum is * equal to valor.
* 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 from(Class enumType, Object value) { Ssortingng methodName = getMethodIdentifier(enumType); return from(enumType, value, methodName); } /** * Returns the Enum of type enumType whose * public method methodName return is * equal to value.
* * @param enumType * @param value * @param methodName * @return */ public static
> E from(Class enumType, Object value, Ssortingng methodName) { EnumSet enumSet = EnumSet.allOf(enumType); for (E en : enumSet) { try { Ssortingng invoke = enumType.getMethod(methodName).invoke(en).toSsortingng(); if (invoke.equals(value.toSsortingng())) { return en; } } catch (Exception e) { return null; } } return null; } private static Ssortingng getMethodIdentifier(Class enumType) { Method[] methods = enumType.getDeclaredMethods(); Ssortingng 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; } }

Exemple:

 public enum Foo { ONE("eins"), TWO("zwei"), THREE("drei"); private Ssortingng value; private Foo(Ssortingng value) { this.value = value; } public Ssortingng getValue() { return value; } } 

EnumUtil.from(Foo.class, "drei") renvoie Foo.THREE , car il utilisera getValue pour correspondre à “drei”, qui est une méthode publique unique, non finale et non statique dans Foo. Dans le cas où Foo a plus que de la méthode publique, pas finale et non statique, par exemple, getTranslate qui retourne “drei”, l’autre méthode peut être utilisée: EnumUtil.from(Foo.class, "drei", "getTranslate") .

Qu’en est-il de?

 public enum MyEnum { FIRST, SECOND, THIRD; public static Optional fromSsortingng(Ssortingng value){ try{ return Optional.of(MyEnum.valueOf(value)); }catch(Exception e){ return Optional.empty(); } } } 

Comme un switch -version n’a pas encore été mentionné, je l’introduis (réutilisation de l’énumération OP):

  private enum Blah { A, B, C, D; public static Blah byName(Ssortingng name) { switch (name) { case "A": return A; case "B": return B; case "C": return C; case "D": return D; default: throw new IllegalArgumentException( "No enum constant " + Blah.class.getCanonicalName() + "." + name); } } } 

Comme cela ne donne aucune valeur supplémentaire à la méthode valueOf(Ssortingng name) , il est logique de définir une méthode supplémentaire si nous voulons avoir un comportement différent. Si nous ne voulons pas générer une IllegalArgumentException nous pouvons changer l’implémentation pour:

  private enum Blah { A, B, C, D; public static Blah valueOfOrDefault(Ssortingng name, Blah defaultValue) { switch (name) { case "A": return A; case "B": return B; case "C": return C; case "D": return D; default: if (defaultValue == null) { throw new NullPointerException(); } return defaultValue; } } } 

En fournissant une valeur par défaut, nous conservons le contrat de Enum.valueOf(Ssortingng name) sans lancer une IllegalArgumentException de cette manière qui, en aucun cas, n’est renvoyée. Par conséquent, nous lançons une NullPointerException si le nom est null et en cas de default si defaultValue est null . Voilà comment fonctionne valueOfOrDefault .

Cette approche adopte la conception de l’interface Map qui fournit une méthode Map.getOrDefault(Object key, V defaultValue) partir de Java 8.

J’aime utiliser ce type de processus pour parsingr les commandes sous forme de chaînes en énumérations. J’ai normalement l’une des énumérations comme “inconnue”, il est donc utile de la retourner lorsque les autres ne sont pas trouvées (même sur une base insensible à la casse) plutôt que nulle (ce qui signifie qu’il n’y a pas de valeur). J’utilise donc cette approche.

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