¿Cómo puedo buscar una enumeración de Java a partir de su valor de cadena?

Me gustaría buscar una enumeración a partir de su valor de cadena (o posiblemente cualquier otro valor). He intentado con el siguiente código, pero no permite la estática en los inicializadores. ¿Hay una manera simple?

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 el método valueOf que se crea automáticamente para cada Enum.

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

Para valores arbitrarios, comience con:

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

Solo muévase más tarde a la implementación del mapa si su generador de perfiles se lo indica.

Sé que está iterando sobre todos los valores, pero con solo 3 valores de enumeración, no vale la pena ningún otro esfuerzo, de hecho, a menos que tengas muchos valores, no me molestaría en un Mapa, será lo suficientemente rápido.

Estás cerca. Para valores arbitrarios, pruebe algo como lo siguiente:

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

La respuesta de @Lyle es bastante peligrosa y he visto que no funciona particularmente si haces que la enumeración sea una clase interna estática. En su lugar, he usado algo como esto que cargará los mapas de BootstrapSingleton antes de las enumeraciones.

Editar esto ya no debería ser un problema con las JVM modernas (JVM 1.6 o superior), pero creo que todavía hay problemas con JRebel, pero no he tenido la oportunidad de volver a probarlo .

Cargarme primero:

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

Ahora cárgalo en el constructor 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 tiene una enumeración interna, puede definir el Mapa sobre la definición de enum y eso (en teoría) debería cargarse antes.

con Java 8 puedes lograrlo de esta manera:

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

¿Y no puedes usar valueOf () ?

Editar: Por cierto, no hay nada que te impida usar static {} en una enumeración.

¡En la Especificación del lenguaje Java 7 hay un ejemplo ! que refleja su pregunta sobre la inicialización del mapa con autorreferencias.

En caso de que ayude a otros, la opción que prefiero, que no figura aquí, usa la funcionalidad 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 reverseLookup = Maps.uniqueIndex(Arrays.asList(Verbosity.values()), Verbosity::getValue); public static Verbosity fromString(final String id) { return reverseLookup.getOrDefault(id, NORMAL); } } 

Con el valor predeterminado puede usar null , puede throw IllegalArgumentException o su fromString podría devolver un Optional , sea cual sea el comportamiento que prefiera.

Tal vez, eche un vistazo a esto. Funciona para mí. El propósito de esto es buscar ‘ROJO’ con ‘/ color_rojo’. Declarar un static map y cargar las enum en él solo una vez aportaría algunos beneficios de rendimiento si las enum son muchas.

 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 ponga sus opiniones.

Puedes definir tu Enum como el siguiente 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 el siguiente enlace para más aclaraciones

Puede usar la función Enum::valueOf() tal como lo sugirieron Gareth Davis y Brad Mace anteriormente, pero asegúrese de manejar la IllegalArgumentException que se lanzaría si la cadena utilizada no está presente en la enumeración.