Buscar enum de Java por valor de cadena


10 Answers

Otra solución si el texto no es el mismo que el valor de enumeración:

public enum Blah {
  A("text1"),
  B("text2"),
  C("text3"),
  D("text4");

  private String text;

  Blah(String text) {
    this.text = text;
  }

  public String getText() {
    return this.text;
  }

  public static Blah fromString(String text) {
    for (Blah b : Blah.values()) {
      if (b.text.equalsIgnoreCase(text)) {
        return b;
      }
    }
    return null;
  }
}
Question

Digamos que tengo una enumeración que es solo

public enum Blah {
    A, B, C, D
}

y me gustaría encontrar el valor enum de una cadena, por ejemplo, "A" que sería Blah.A ¿Cómo sería posible hacer esto?

¿Es el Enum.valueOf() el método que necesito? Si es así, ¿cómo usaría esto?




Otra forma de hacerlo es usar el name() implícito del método estático name() de Enum. name devolverá la cadena exacta utilizada para crear esa enumeración que se puede usar para verificar contra la cadena proporcionada:

public enum Blah {

    A, B, C, D;

    public static Blah getEnum(String s){
        if(A.name().equals(s)){
            return A;
        }else if(B.name().equals(s)){
            return B;
        }else if(C.name().equals(s)){
            return C;
        }else if (D.name().equals(s)){
            return D;
        }
        throw new IllegalArgumentException("No Enum specified for this string");
    }
}

Pruebas:

System.out.println(Blah.getEnum("B").name());

//it will print B  B

inspiración: 10 ejemplos de Enum en Java




Si no desea escribir su propia utilidad, use la biblioteca de guava de Google:

Enums.getIfPresent(Blah.class, "A")

A diferencia de la función incorporada en java, te permite verificar si A está presente en Blah y no lanza una excepción.




En Java 8, el patrón de Mapa estático es aún más fácil y es mi método preferido. Si desea utilizar Enum with Jackson, puede anular toString y usar eso en lugar de name, luego anotar con @JsonValue

public enum MyEnum {
    BAR,
    BAZ;
    private static final Map<String, MyEnum> MAP = Stream.of(MyEnum.values()).collect(Collectors.toMap(Enum::name, Function.identity()));
    public static MyEnum fromName(String name){
        return MAP.get(name);
    }
}

public enum MyEnumForJson {
    BAR("bar"),
    BAZ("baz");
    private static final Map<String, MyEnumForJson> MAP = Stream.of(MyEnumForJson.values()).collect(Collectors.toMap(Object::toString, Function.identity()));
    private final String value;

    MyEnumForJson(String value) {
        this.value = value;
    }

    @JsonValue
    @Override
    public String toString() {
        return value;
    }

    public static MyEnumForJson fromValue(String value){
        return MAP.get(value);
    }
}



Otra utilidad que se captura de forma inversa. Usando un valor que identifica ese Enum, no desde su nombre.

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.EnumSet;

public class EnumUtil {

    /**
     * Returns the <code>Enum</code> of type <code>enumType</code> whose a 
     * public method return value of this Enum is 
     * equal to <code>valor</code>.<br/>
     * Such method should be unique public, not final and static method 
     * declared in Enum.
     * In case of more than one method in match those conditions
     * its first one will be chosen.
     * 
     * @param enumType
     * @param value
     * @return 
     */
    public static <E extends Enum<E>> E from(Class<E> enumType, Object value) {
        String methodName = getMethodIdentifier(enumType);
        return from(enumType, value, methodName);
    }

    /**
     * Returns the <code>Enum</code> of type <code>enumType</code> whose  
     * public method <code>methodName</code> return is 
     * equal to <code>value</code>.<br/>
     *
     * @param enumType
     * @param value
     * @param methodName
     * @return
     */
    public static <E extends Enum<E>> E from(Class<E> enumType, Object value, String methodName) {
        EnumSet<E> enumSet = EnumSet.allOf(enumType);
        for (E en : enumSet) {
            try {
                String invoke = enumType.getMethod(methodName).invoke(en).toString();
                if (invoke.equals(value.toString())) {
                    return en;
                }
            } catch (Exception e) {
                return null;
            }
        }
        return null;
    }

    private static String getMethodIdentifier(Class<?> enumType) {
        Method[] methods = enumType.getDeclaredMethods();
        String name = null;
        for (Method method : methods) {
            int mod = method.getModifiers();
            if (Modifier.isPublic(mod) && !Modifier.isStatic(mod) && !Modifier.isFinal(mod)) {
                name = method.getName();
                break;
            }
        }
        return name;
    }
}

Ejemplo:

public enum Foo {
    ONE("eins"), TWO("zwei"), THREE("drei");

    private String value;

    private Foo(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }
}

EnumUtil.from(Foo.class, "drei") devuelve Foo.THREE , porque usará getValue para que coincida con "drei", que es un método público único, no final y no estático en Foo. En caso de que Foo tenga más que un método público, no final y no estático, por ejemplo, getTranslate que devuelve "drei", se puede usar el otro método: EnumUtil.from(Foo.class, "drei", "getTranslate") .




Usa el patrón de Joshua Bloch, Effective Java :

(simplificado por brevedad)

enum MyEnum {
  ENUM_1("A"),
  ENUM_2("B");

  private String name;

  private static final Map<String,MyEnum> ENUM_MAP;

  MyEnum (String name) {
    this.name = name;
  }

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

  // Build an immutable map of String name to enum pairs.
  // Any Map impl can be used.

  static {
    Map<String,MyEnum> map = new ConcurrentHashMap<String,MyEnum>();
    for (MyEnum instance : MyEnum.values()) {
      map.put(instance.getName(),instance);
    }
    ENUM_MAP = Collections.unmodifiableMap(map);
  }

  public static MyEnum get (String name) {
    return ENUM_MAP.get(name);
  }
}

Ver también:

Oracle Java Example utilizando Enum y Map of instances

Orden de ejecución de bloques estáticos en un tipo Enum

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




Solución usando las bibliotecas de guayaba El método getPlanet () no distingue entre mayúsculas y minúsculas, por lo que getPlanet ("MerCUrY") devolverá Planet.MERCURY.

package com.universe.solarsystem.planets;
import org.apache.commons.lang3.StringUtils;
import com.google.common.base.Enums;
import com.google.common.base.Optional;

//Pluto and Eris are dwarf planets, who cares!
public enum Planet {
   MERCURY,
   VENUS,
   EARTH,
   MARS,
   JUPITER,
   SATURN,
   URANUS,
   NEPTUNE;

   public static Planet getPlanet(String name) {
      String val = StringUtils.trimToEmpty(name).toUpperCase();
      Optional <Planet> possible = Enums.getIfPresent(Planet.class, val);
      if (!possible.isPresent()) {
         throw new IllegalArgumentException(val + "? There is no such planet!");
      }
      return possible.get();
   }
}



Método O (1) inspirado en el código de ahorro generado que utiliza un hashmap.

public enum USER {
        STUDENT("jon",0),TEACHER("tom",1);

        private static final Map<String, Integer> map = new HashMap<>();

        static {
                for (USER user : EnumSet.allOf(USER.class)) {
                        map.put(user.getTypeName(), user.getIndex());
                }
        }

        public static int findIndexByTypeName(String typeName) {
                return map.get(typeName);
        }

        private USER(String typeName,int index){
                this.typeName = typeName;
                this.index = index;
        }
        private String typeName;
        private int index;
        public String getTypeName() {
                return typeName;
        }
        public void setTypeName(String typeName) {
                this.typeName = typeName;
        }
        public int getIndex() {
                return index;
        }
        public void setIndex(int index) {
                this.index = index;
        }

}



También debe tener cuidado con su caso. Déjame explicarte: hacer Blah.valueOf("A") funciona, pero Blah.valueOf("a") no funcionará. Entonces otra vez Blah.valueOf("a".toUpperCase(Locale.ENGLISH)) funcionaría.

editar
Se cambió toUpperCase por toUpperCase(Locale.ENGLISH) función de tc. comentario y los documentos de Java

edit2 En Android debes usar Locale.US , como señala sulai .




public static MyEnum getFromValue(String value) {
    MyEnum resp = null;
    MyEnum nodes[] = values();
    for(int i = 0; i < nodes.length; i++) {
        if(nodes[i].value.equals(value)) {
            resp = nodes[i];
            break;
        }
    }
    return resp;
}



Me gusta usar este tipo de proceso para analizar comandos como cadenas en enumeraciones. Normalmente tengo una de las enumeraciones como "desconocida", por lo que ayuda a que la devuelvan cuando no se encuentran las demás (incluso sin distinción de mayúsculas y minúsculas) en lugar de nulas (lo que significa que no hay ningún valor). Por lo tanto, uso este enfoque.

static <E extends Enum<E>> Enum getEnumValue(String what, Class<E> enumClass) {
    Enum<E> unknown=null;
    for (Enum<E> enumVal: enumClass.getEnumConstants()) {  
        if (what.compareToIgnoreCase(enumVal.name()) == 0) {
            return enumVal;
        }
        if (enumVal.name().compareToIgnoreCase("unknown") == 0) {
            unknown=enumVal;
        }
    }  
    return unknown;
}



Related



Tags

java java   enums