Como posso procurar um enum Java a partir de seu valor String?

Eu gostaria de procurar um enum de seu valor de seqüência de caracteres (ou possivelmente qualquer outro valor). Eu tentei o código a seguir, mas não permite estática em inicializadores. Existe uma maneira simples?

public enum Verbosity { BRIEF, NORMAL, FULL; private static Map stringMap = new HashMap(); private Verbosity() { stringMap.put(this.toString(), this); } public static Verbosity getVerbosity(String key) { return stringMap.get(key); } }; 

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

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

Para valores arbitrários, comece com:

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

Apenas siga adiante para Mapear a implementação, se o seu profiler lhe disser.

Eu sei que é iterar sobre todos os valores, mas com apenas 3 valores enum não vale a pena nenhum outro esforço, na verdade, a menos que você tenha muitos valores que eu não me importaria com um mapa, ele será rápido o suficiente.

Você está perto. Para valores arbitrários, tente 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 lookup = new HashMap(); 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); } } 

A resposta de @Lyle é bastante perigosa e eu tenho visto que não funciona particularmente se você fizer do enum uma class interna estática. Em vez disso, usei algo como isto, que carregará os mapas do BootstrapSingleton antes dos enums.

Editar isso não deve ser mais um problema com as JVMs modernas (JVM 1.6 ou superior), mas eu acho que ainda existem problemas com o JRebel, mas eu não tive a chance de testá-lo novamente .

Me carregue primeiro:

  public final class BootstrapSingleton { // Reverse-lookup map for getting a day from an abbreviation public static final Map lookup = new HashMap(); } 

Agora carregue-o 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ê tiver um enum interno, basta definir o Mapa acima da definição enum e que (em teoria) deve ser carregado antes.

com o Java 8 você pode conseguir com este caminho:

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

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

Edit: Btw, não há nada que o impeça de usar {} estático em um enum.

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

No caso de ajudar os outros, a opção que eu prefiro, que não está listada aqui, usa a funcionalidade Mapas da Guava :

 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 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 você pode usar null , você pode throw IllegalArgumentException ou seu fromString pode retornar um Optional , qualquer que seja o comportamento que você preferir.

Talvez, dê uma olhada nisso. Está funcionando para mim. O objective disto é procurar ‘RED’ com ‘/ red_color’. Declarar um static map e carregar os enum s nele somente uma vez traria alguns benefícios de desempenho se os enum s forem muitos.

 public class Mapper { public enum Maps { COLOR_RED("/red_color", "RED"); private final String code; private final String description; private static Map 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(); for (Maps s : Maps.values()) { mMap.put(s.code, s.description); } } } } 

Por favor, coloque em seus opinons.

Você pode definir seu Enum como o 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(); } }; 

Veja o link a seguir para mais esclarecimentos

Você pode usar a function Enum::valueOf() como sugerido por Gareth Davis & Brad Mace acima, mas certifique-se de manipular a IllegalArgumentException que seria lançada se a string usada não estivesse presente no enum.