Pergunta

Gostaria de pesquisar uma enumeração de seu valor string (ou, eventualmente, qualquer outro valor). Eu tentei o seguinte código, mas ele não permite estática em initialisers. Existe uma maneira simples?

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);
    }
};
Foi útil?

Solução

Use o método valueOf que é criado automaticamente para cada Enum.

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

Para valores arbitrários começar com:

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

Apenas seguir em frente depois da implementação do mapa se o seu profiler diz-lhe para.

Eu sei que é a iteração sobre todos os valores, mas com apenas 3 valores enum é não vale a pena qualquer outro esforço, na verdade, a menos que você tem um monte de valores eu não me incomodaria com um mapa que vai ser rápido o suficiente.

Outras dicas

Você está perto. Para valores arbitrários, tentar algo como o seguinte:

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

com Java 8 você pode conseguir com esta maneira:

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

@ resposta de Lyle é bastante perigoso e eu já vi isso não funcionar, especialmente se você fazer a enumeração de uma classe interna estática. Em vez disso eu usei algo parecido com isto que irá carregar os mapas BootstrapSingleton antes dos enums.

Editar isso não deve ser um problema mais com JVMs modernas (JVM 1.6 ou superior), mas eu acho que ainda há problemas com JRebel mas eu não tive a chance de reteste it .

Coloque-me em primeiro lugar:

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

Agora, carregá-lo no construtor 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 você tem um enum interior você pode apenas definir o mapa acima a definição enum e que (em teoria) deve começar carregado antes.

E você não pode usar valueOf () ?

Edit:. Aliás, não há nada que você parar de usar estática {} em um enum

Na especificação linguagem Java 7 há um um exemplo ! que reflecte a sua pergunta sobre a inicialização do mapa com auto-referências.

Em caso de ajuda outros, a opção que eu prefiro, que não está aqui, usos Guava funcionalidade Mapas :

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

Com o padrão que você pode usar null, você pode throw IllegalArgumentException ou o seu fromString poderia retornar um Optional, qualquer comportamento que você preferir.

Talvez, dê uma olhada nisso. Seu trabalho para mim. O objetivo deste é para procurar 'RED' com '/ red_color'. Declarando uma static map e carregar os enums para ele apenas uma vez traria alguns benefícios de desempenho se os enums são muitos.

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

Por favor, coloque em seus opinons.

Você pode definir seu Enum como seguinte código:

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

Ver seguinte link para mais esclarecimentos

desde java 8 você pode inicializar o mapa em uma única linha e sem bloco estático

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

Você pode usar a função Enum::valueOf() como sugerido por Gareth Davis & Brad Mace acima, mas certifique-se de lidar com a IllegalArgumentException que seria lançada se a string usada não está presente na enumeração.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top