with Recherche Java enum par valeur de chaîne




java enum with value (19)

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;
}

Dire que j'ai une énumération 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 pourrais-je l'utiliser?



Pour ajouter aux réponses précédentes, et aborder certaines des discussions autour des nulls et des NPE, j'utilise les options gaussiennes pour gérer les cas absents / invalides. Cela fonctionne très bien pour l'analyse d'URI / paramètres.

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();
        }
    }
}

Pour ceux qui ne sont pas au courant, voici quelques informations sur comment éviter null avec Optional: https://code.google.com/p/guava-libraries/wiki/UsingAndAvoidingNullExplained#Optional


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

modifier
Changé toUpperCase to toUpperCase(Locale.ENGLISH) basé sur tc. commenter et les docs java

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


Solution en utilisant des bibliothèques de Guava. La méthode getPlanet () est insensible à la casse, donc getPlanet ("MerCUrY") retournera 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();
   }
}

java.lang.Enum définit plusieurs méthodes utiles, disponibles pour tous les types d'énumération dans 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 Enum constante en Java, comme indiqué ci-dessous.
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

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


Utiliser Blah.valueOf(string) est préférable mais vous pouvez aussi utiliser Enum.valueOf(Blah.class, string) .


Voici une méthode qui peut le faire pour tout Enum, et 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 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()
    ));
}

Voici un utilitaire utile que j'utilise:

/**
 * 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;
}

Ensuite, dans ma classe enum, j'ai généralement ceci pour sauver un peu de frappe:

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

Si vos enums ne sont pas tous en majuscules, modifiez simplement la ligne Enum.valueOf .

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


Une autre façon de le faire en utilisant la méthode statique implicite name() de Enum. name retournera 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(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");
    }
}

Essai:

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

//it will print B  B

inspiration: 10 exemples d'énumération en Java


Une autre solution si le texte n'est pas le même que la valeur d'énumération:

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;
  }
}

Ajoutant à la réponse la mieux notée, avec un utilitaire utile ...

valueOf() renvoie deux exceptions différentes dans les cas où il n'aime pas son entrée.

  • IllegalArgumentException
  • NullPointerExeption

Si vos besoins sont tels que vous n'avez aucune garantie que votre chaîne correspondra définitivement à une valeur enum, par exemple si les données de chaîne proviennent d'une base de données et pourraient contenir une ancienne version de l'énumération, vous devrez les gérer souvent...

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

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;
        }
    }

Utilisez-le comme ceci:

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
}

Vous pouvez avoir besoin de ceci:

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;
    }
}

Un ajout de plus:

   public static String fromEnumName(String 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 d'énumération stringifié. Par exemple, si vous fournissez "PERSON" dans fromEnumName, il vous renverra la valeur de Enum, c'est-à-dire "Person"


J'aime utiliser ce genre de processus pour analyser les commandes comme des chaînes dans les énumérations. J'ai normalement l'une des énumérations comme "inconnue" donc il est utile d'avoir cela retourné quand les autres ne sont pas trouvés (même sur une base insensible à la casse) plutôt que null (ce qui signifie qu'il n'y a pas de valeur). Par conséquent, j'utilise cette approche.

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;
}

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

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

Contrairement à la fonction java intégrée, elle vérifie si A est présent dans Blah et ne lance pas d'exception.


Méthode O (1) inspirée du code généré par l'épargne qui utilise une hashmap.

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;
        }

}

Qu'en est-il de?

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();
        }
    }
}

Mes 2 cents ici: en utilisant Java8 Streams + en vérifiant une chaîne exacte:

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 fromString(String 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 à fromString() depuis l'avoir nommé en utilisant cette convention, vous obtiendrez quelques avantages du langage Java lui-même; par exemple:

  1. Conversion directe des types à l'annotation HeaderParam

Utilisez le motif de Joshua Bloch, Java efficace :

(simplifié pour la brièveté)

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);
  }
}

Regarde aussi:

Oracle Java Exemple utilisant Enum et Map des instances

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

Comment puis-je rechercher une énumération Java à partir de sa valeur String







enums