Domanda

Vorrei cercare l'enum dal suo valore di stringa (o eventualmente qualsiasi altro valore). Ho provato il seguente codice, ma non permette statica in inizializzatori. C'è un modo semplice?

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);
    }
};
È stato utile?

Soluzione

Utilizzare il metodo valueOf che viene creato automaticamente per ogni Enum.

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

Per i valori arbitrari iniziano con:

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

passare solo in un secondo momento a Map implementazione se il profiler ti dice di.

Lo so che è iterare su tutti i valori, ma con solo 3 valori enum non è certo la pena di qualsiasi altro sforzo, di fatto se non avete un sacco di valori non vorrei perdere tempo con una mappa sarà abbastanza veloce.

Altri suggerimenti

Stai vicino. Per i valori arbitrari, provare qualcosa di simile al seguente:

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

con Java 8 è possibile ottenere con questo modo:

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

@ risposta di Lyle è piuttosto pericoloso e ho visto che non funziona soprattutto se si effettua l'enumerazione di una classe interna statica. Invece ho usato qualcosa di simile che caricare le mappe BootstrapSingleton prima delle enumerazioni.

Modifica questo non dovrebbe essere più un problema con la JVM moderni (JVM 1.6 o superiore), ma penso che ci sono ancora problemi con JRebel ma non ho avuto la possibilità di retest è .

Carica me per primo:

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

Ora caricarlo nel costruttore 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);
        }
    }

Se si dispone di un enum interno si può solo definire la mappa sopra la definizione enum e che (in teoria) dovrebbe ottenere caricato prima.

E non è possibile utilizzare valueOf () ?

Modifica:. Btw, non c'è nulla ti impedisce di utilizzare static {} in un enum

Nel linguaggio Java Specification 7 c'è un un esempio di ! che riflette la tua domanda sul l'inizializzazione della mappa con le auto-riferimenti.

Nel caso in cui aiuta gli altri, l'opzione che preferisco, che non è elencato qui, usi di Guava Mappe funzionalità :

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

Con l'impostazione predefinita è possibile utilizzare null, è possibile throw IllegalArgumentException o la vostra fromString potrebbe restituire un Optional, qualsiasi comportamento che si preferisce.

Forse, date un'occhiata a questo. Il suo lavoro per me. Lo scopo di questo è ad occhiata 'RED' con '/ red_color'. Dichiarare un static map e il caricamento dei enums in esso solo una volta avrebbe portato alcuni benefici di prestazioni se i enums sono molti.

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

Si prega di inserire nei vostri opinons.

È possibile definire l'Enum come seguente codice:

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

Vedi seguente link per ulteriori chiarimenti

dal momento che Java 8 è possibile inizializzare la mappa in una sola riga e senza blocco statico

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

È possibile utilizzare la funzione Enum::valueOf() come suggerito da Gareth Davis & Brad Mace sopra, ma assicuratevi di gestire la IllegalArgumentException che sarebbe generata se la stringa utilizzata non è presente nel enum.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top