web-dev-qa-db-fra.com

Comment puis-je rechercher un Java enum à partir de sa valeur String?

Je voudrais rechercher une énumération de sa valeur de chaîne (ou éventuellement de toute autre valeur). J'ai essayé le code suivant mais il n'autorise pas les initialiseurs statiques. Y a-t-il un moyen simple?

public enum Verbosity {

    BRIEF, NORMAL, FULL;

    private static Map<String, Verbosity> stringMap = new HashMap<String, Verbosity>();

    private Verbosity() {
        stringMap.put(this.toString(), this);
    }

    public static Verbosity getVerbosity(String key) {
        return stringMap.get(key);
    }
};
138
peter.murray.rust

Utilisez la méthode valueOf qui est créée automatiquement pour chaque énumération.

Verbosity.valueOf("BRIEF") == Verbosity.BRIEF

Pour les valeurs arbitraires, commencez par:

public static Verbosity findByAbbr(String abbr){
    for(Verbosity v : values()){
        if( v.abbr().equals(abbr)){
            return v;
        }
    }
    return null;
}

Ne passez à la mise en œuvre de la carte que si votre profileur vous le demande.

Je sais que c'est une itération de toutes les valeurs, mais avec seulement 3 valeurs d'énum, ​​cela ne vaut pas la peine de faire un autre effort. En fait, à moins que vous ayez beaucoup de valeurs, je ne m'embêterais pas avec une carte, elle sera assez rapide.

213
Gareth Davis

Tu es proche. Pour des valeurs arbitraires, essayez l'une des solutions suivantes:

public enum Day { 

    MONDAY("M"), TUESDAY("T"), WEDNESDAY("W"),
    THURSDAY("R"), FRIDAY("F"), SATURDAY("Sa"), SUNDAY("Su"), ;

    private final String abbreviation;

    // Reverse-lookup map for getting a day from an abbreviation
    private static final Map<String, Day> lookup = new HashMap<String, Day>();

    static {
        for (Day d : Day.values()) {
            lookup.put(d.getAbbreviation(), d);
        }
    }

    private Day(String abbreviation) {
        this.abbreviation = abbreviation;
    }

    public String getAbbreviation() {
        return abbreviation;
    }

    public static Day get(String abbreviation) {
        return lookup.get(abbreviation);
    }
}
123
Lyle

avec Java 8, vous pouvez obtenir de cette manière:

public static Verbosity findByAbbr(final String abbr){
    return Arrays.stream(values()).filter(value -> value.abbr().equals(abbr)).findFirst().orElse(null);
}
15
Lam Le

La réponse de @ Lyle est plutôt dangereuse et je l'ai déjà vu ne pas fonctionner, surtout si vous faites de l'énum une classe interne statique. Au lieu de cela, j'ai utilisé quelque chose comme ceci qui chargera les cartes BootstrapSingleton avant les enums.

Edit cela ne devrait plus être un problème avec les JVM modernes (JVM 1.6 ou supérieure) mais je pense qu'il y a toujours des problèmes avec JRebel mais je n'ai pas eu une chance de le retester .

Charge moi d'abord:

   public final class BootstrapSingleton {

        // Reverse-lookup map for getting a day from an abbreviation
        public static final Map<String, Day> lookup = new HashMap<String, Day>();
   }

Maintenant, chargez-le dans le constructeur enum:

   public enum Day { 
        MONDAY("M"), TUESDAY("T"), WEDNESDAY("W"),
        THURSDAY("R"), FRIDAY("F"), SATURDAY("Sa"), SUNDAY("Su"), ;

        private final String abbreviation;

        private Day(String abbreviation) {
            this.abbreviation = abbreviation;
            BootstrapSingleton.lookup.put(abbreviation, this);
        }

        public String getAbbreviation() {
            return abbreviation;
        }

        public static Day get(String abbreviation) {
            return lookup.get(abbreviation);
        }
    }

Si vous avez un enum interne, vous pouvez simplement définir la carte au-dessus de la définition de l’énum et cela (en théorie) devrait être chargé avant.

13
Adam Gent

Et vous ne pouvez pas utiliser valueOf () ?

Edit: Btw, rien ne vous empêche d’utiliser static {} dans un enum.

6
Fredrik

Si cela peut aider les autres, l’option que je préfère, qui ne figure pas ici, utilise fonctionnalité de Guava's Maps :

public enum Vebosity {
    BRIEF("BRIEF"),
    NORMAL("NORMAL"),
    FULL("FULL");

    private String value;
    private Verbosity(final String value) {
        this.value = value;
    }

    public String getValue() {
        return this.value;
    }

    private static ImmutableMap<String, Verbosity> reverseLookup = 
            Maps.uniqueIndex(Arrays.asList(Verbosity.values()), Verbosity::getValue);

    public static Verbosity fromString(final String id) {
        return reverseLookup.getOrDefault(id, NORMAL);
    }
}

Par défaut, vous pouvez utiliser null, vous pouvez throw IllegalArgumentException ou votre fromString peut renvoyer un Optional, quel que soit le comportement que vous préférez.

5
Chad Befus

Dans la Java Spécification du langage 7, il existe un n exemple ! cela reflète votre question sur l’initialisation de la carte avec des auto-références.

5
mbonato

Peut-être, jetez un oeil à cela. Cela fonctionne pour moi. Le but de ceci est de rechercher 'RED' avec '/ red_color'. Déclarer un static map et charger le enums une seule fois apporterait des avantages en termes de performances si les enums sont nombreux.

public class Mapper {

public enum Maps {

    COLOR_RED("/red_color", "RED");

    private final String code;
    private final String description;
    private static Map<String, String> mMap;

    private Maps(String code, String description) {
        this.code = code;
        this.description = description;
    }

    public String getCode() {
        return name();
    }

    public String getDescription() {
        return description;
    }

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

    public static String getColorName(String uri) {
        if (mMap == null) {
            initializeMapping();
        }
        if (mMap.containsKey(uri)) {
            return mMap.get(uri);
        }
        return null;
    }

    private static void initializeMapping() {
        mMap = new HashMap<String, String>();
        for (Maps s : Maps.values()) {
            mMap.put(s.code, s.description);
        }
    }
}
}

S'il vous plaît mettez dans vos opinions.

1
Midhun

Vous pouvez définir votre énumération comme code suivant:

public enum Verbosity 
{
   BRIEF, NORMAL, FULL, ACTION_NOT_VALID;
   private int value;

   public int getValue()
   {
     return this.value;
   } 

   public static final Verbosity getVerbosityByValue(int value)
   {
     for(Verbosity verbosity : Verbosity.values())
     {
        if(verbosity.getValue() == value)
            return verbosity ;
     }

     return ACTION_NOT_VALID;
   }

   @Override
   public String toString()
   {
      return ((Integer)this.getValue()).toString();
   }
};

Voir le lien suivant pour plus de précisions

0
Vinay Sharma

depuis Java 8, vous pouvez initialiser la carte en une seule ligne et sans bloc statique

private static Map<String, Verbosity> stringMap = Arrays.stream(values())
                 .collect(Collectors.toMap(Enum::toString, Function.identity()));
0
Adrian