Tutorial :Lookup Java enum by string value



Question:

Say I have an enum which is just

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

and I would like to find the enum value of a string, for example "A" which would be Blah.A. How would it be possible to do this?

Is the Enum.valueOf() the method I need? If so, how would I use this?


Solution:1

Yes, Blah.valueOf("A") will give you Blah.A.

Note that the name must be an exact match, including case: Blah.valueOf("a") and Blah.valueOf("A ") both throw an IllegalArgumentException.

The static methods valueOf() and values() are created at compile time and do not appear in source code. They do appear in Javadoc, though; for example, Dialog.ModalityType shows both methods.


Solution:2

Another solution if the text is not the same to the enumeration value:

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


Solution:3

Here's a nifty utility I use:

/**   * A common method for all enums since they can't have another base class   * @param <T> Enum type   * @param c enum type. All enums must be all caps.   * @param string case insensitive   * @return corresponding enum, or null   */  public static <T extends Enum<T>> T getEnumFromString(Class<T> c, String string) {      if( c != null && string != null ) {          try {              return Enum.valueOf(c, string.trim().toUpperCase());          } catch(IllegalArgumentException ex) {          }      }      return null;  }  

Then in my enum class I usually have this to save some typing:

public static MyEnum fromString(String name) {      return getEnumFromString(MyEnum.class, name);  }  

If your enums are not all caps, just change the Enum.valueOf line.

Too bad I can't use T.class for Enum.valueOf as T is erased.


Solution:4

You should also be careful with your case. Let me explain: doing Blah.valueOf("A") works, but Blah.valueOf("a") will not work. Then again Blah.valueOf("a".toUpperCase(Locale.ENGLISH)) would work.

edit
Changed toUpperCase to toUpperCase(Locale.ENGLISH) based on tc. comment and the java docs

edit2 On android you should use Locale.US, as sulai points out.


Solution:5

Here's a method that can do it for any Enum, and is case insensitive.

/**    * Finds the value of the given enumeration by name, case-insensitive.    * Throws an IllegalArgumentException if no match is found.     **/  public static <T extends Enum<T>> T valueOfIgnoreCase(          Class<T> enumeration, String name) {        for (T enumValue : enumeration.getEnumConstants()) {          if (enumValue.name().equalsIgnoreCase(name)) {              return enumValue;          }      }        throw new IllegalArgumentException(String.format(          "There is no value with name '%s' in Enum %s",          name, enumeration.getName()      ));  }  


Solution:6

Use the pattern from Joshua Bloch, Effective Java:

(simplified for brevity)

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

Also see:

Oracle Java Example using Enum and Map of instances

Execution order of of static blocks in an Enum type

How can I lookup a Java enum from its String value


Solution:7

Using Blah.valueOf(string) is best but you can use Enum.valueOf(Blah.class, string) as well.


Solution:8

If you don't want to write your own utility use Google's library:

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

Unlike the built in java function it let's you check if A is present in Blah and doesn't throw an exception.


Solution:9

You may need to this :

public enum ObjectType {      PERSON("Person");        public String parameterName;        ObjectType(String parameterName) {          this.parameterName = parameterName;      }        public String getParameterName() {          return this.parameterName;      }        //From String method will return you the Enum for the provided input string      public static ObjectType fromString(String parameterName) {          if (parameterName != null) {              for (ObjectType objType : ObjectType.values()) {                  if (parameterName.equalsIgnoreCase(objType.parameterName)) {                      return objType;                  }              }          }          return null;      }  }  

One More Addition :

   public static String fromEnumName(String parameterName) {          if (parameterName != null) {              for (DQJ objType : DQJ.values()) {                  if (parameterName.equalsIgnoreCase(objType.name())) {                      return objType.parameterName;                  }              }          }          return null;      }  

This will return you the Value by a Stringified Enum Name For e.g. if you provide "PERSON" in the fromEnumName it'll return you the Value of Enum i.e. "Person"


Solution:10

Another way of doing this by using implicit static method name() of Enum. name will return the exact string used to create that enum which can be used to check against provided string:

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

Testing:

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

//it will print B  B  

inspiration: 10 Examples of Enum in Java


Solution:11

My 2 cents here: using Java8 Streams + checking an exact string:

public enum MyEnum {      VALUE_1("Super"),      VALUE_2("Rainbow"),      VALUE_3("Dash"),      VALUE_3("Rocks");        private final String value;        MyEnum(String value) {          this.value = value;      }        /**       * @return the Enum representation for the given string.       * @throws IllegalArgumentException if unknown string.       */      public static MyEnum fromString(String s) throws IllegalArgumentException {          return Arrays.stream(MyEnum.values())                  .filter(v -> v.value.equals(s))                  .findFirst();                  .orElseThrow(() -> new IllegalArgumentException("unknown value: " + s));      }  }  

** EDIT **

Renamed the function to fromString() since naming it using that convention, you'll obtain some benefits from Java language itself; for example:

  1. Direct conversion of types at HeaderParam annotation


Solution:12

In Java 8 or later, using Streams:

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 fromText(String text) {          return Arrays.stream(values())            .filter(bl -> bl.text.equalsIgnoreCase(text))            .findFirst()            .orElse(null);      }  }  


Solution:13

Solution using Guava libraries. Method getPlanet () is case insensitive, so getPlanet ("MerCUrY") will return 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();     }  }  


Solution:14

To add to the previous answers, and address some of the discussions around nulls and NPE I'm using Guava Optionals to handle absent/invalid cases. This works great for URI/parameter parsing.

public enum E {      A,B,C;      public static Optional<E> fromString(String s) {          try {              return Optional.of(E.valueOf(s.toUpperCase()));          } catch (IllegalArgumentException|NullPointerException e) {              return Optional.absent();          }      }  }  

For those not aware, here's some more info on avoiding null with Optional: https://code.google.com/p/guava-libraries/wiki/UsingAndAvoidingNullExplained#Optional


Solution:15

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


Solution:16

O(1) method inspired from thrift generated code which utilize a 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;          }    }  


Solution:17

In Java 8 the static Map pattern is even easier and is my preffered method. If you want to use the Enum with Jackson you can override toString and use that instead of name, then annotate with @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);      }  }  


Solution:18

java.lang.Enum defines several useful methods, which is available to all enumeration type in Java:

  • You can use name() method to get name of any Enum constants. String literal used to write enum constants is their name.
  • Similarly values() method can be used to get an array of all Enum constants from an Enum type.
  • And for the asked question, you can use valueOf() method to convert any String to Enum constant in Java, as shown below.
public class EnumDemo06 {      public static void main(String args[]) {          Gender fromString = Gender.valueOf("MALE");          System.out.println("Gender.MALE.name() : " + fromString.name());      }        private enum Gender {          MALE, FEMALE;      }  }    Output:  Gender.MALE.name() : MALE  

In this code snippet, valueOf() method returns an Enum constant Gender.MALE, calling name on that returns "MALE".


Solution:19

Apache's commons-lang library has a static function org.apache.commons.lang3.EnumUtils.getEnum which will map a String to your Enum type. Same answer essentially as Geoffreys but why roll your own when it's out there in the wild already.


Solution:20

Adding on to the top rated answer, with a helpful utility...

valueOf() throws two different Exceptions in cases where it doesn't like its input.

  • IllegalArgumentException
  • NullPointerExeption

If your requirements are such that you don't have any guarantee that your String will definitely match an enum value, for example if the String data comes from a database and could contain old version of the enum, then you'll need to handle these often...

So here's a reusable method I wrote which allows us to define a default Enum to be returned if the String we pass doesn't match.

private static <T extends Enum<T>> T valueOf( String name , T defaultVal) {          try {              return Enum.valueOf(defaultVal.getDeclaringClass() , name);          } catch (IllegalArgumentException | NullPointerException e) {              return defaultVal;          }      }  

Use it like this:

public enum MYTHINGS {      THINGONE,      THINGTWO  }    public static void main(String [] asd) {    valueOf("THINGTWO" , MYTHINGS.THINGONE);//returns MYTHINGS.THINGTWO    valueOf("THINGZERO" , MYTHINGS.THINGONE);//returns MYTHINGS.THINGONE  }  


Solution:21

Another utility capturing in reverse way. Using a value which identify that Enum, not from its name.

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

Example:

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") returns Foo.THREE, because it will use getValue to match "drei", which is unique public, not final and not static method in Foo. In case Foo has more than on public, not final and not static method, for example, getTranslate which returns "drei", the other method can be used: EnumUtil.from(Foo.class, "drei", "getTranslate").


Solution:22

I like to use this sort of process to parse commands as strings into enumerations. I normally have one of the enumerations as "unknown" so it helps to have that returned when the others are not found (even on a case insensitive basis) rather than null (that meaning there is no value). Hence I use this approach.

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


Solution:23

What about?

public enum MyEnum {      FIRST,      SECOND,      THIRD;        public static Optional<MyEnum> fromString(String value){          try{              return Optional.of(MyEnum.valueOf(value));          }catch(Exception e){              return Optional.empty();          }      }  }  

Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »