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?
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.
Answered 2023-09-20 20:32:32
Blah.valueOf("A")
method is case sensitive and doesn't tolerate extraneous whitespace, thus the alternate solution proposed below by @JoséMi. - anyone toString()
value, no, I wouldn't say that. name()
will get you the actual defined name of the enum constant unless you override it. - anyone enum Blah {...}
definition shouldn't try to declare its own values
nor valuesOf
. It's like how you can write "AnyTypeName.class" even though you never actually declared a "class" member variable; the compiler makes it all Just Work. (This answer may no longer be useful to you 3 months later, but just in case.) - anyone Another solution if the text is not the same as 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;
}
}
Answered 2023-09-20 20:32:32
throw new IllegalArgumentException("No constant with text " + text + " found")
would be better than return null
. - anyone 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().toLowerCase(),instance);
}
ENUM_MAP = Collections.unmodifiableMap(map);
}
public static MyEnum get (String name) {
return ENUM_MAP.get(name.toLowerCase());
}
}
Also see:
Oracle Java Example using Enum and Map of instances
Answered 2023-09-20 20:32:32
Stream.of(MyEnum.values()).collect(toMap(Enum::name, identity()))
I also recommend overriding toString() (passed in through constructor) and using that instead of name, especially if the Enum is associated with serializable data as this lets you control the casing without giving Sonar a fit. - anyone ConcurrentHashMap
here, where the map is never modified after initialization. Hence why even e.g. the example in the JLS itself uses a regular HashMap
. - anyone 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.
It is too bad I can't use T.class
for Enum.valueOf
as T
is erased.
Answered 2023-09-20 20:32:32
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.
On Android you should use Locale.US
, as sulai points out.
Answered 2023-09-20 20:32:32
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 Optional<Blah> fromText(String text) {
return Arrays.stream(values())
.filter(bl -> bl.text.equalsIgnoreCase(text))
.findFirst();
}
}
Answered 2023-09-20 20:32:32
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()
));
}
Answered 2023-09-20 20:32:32
Using Blah.valueOf(string)
is best, but you can use Enum.valueOf(Blah.class, string)
as well.
Answered 2023-09-20 20:32:32
My two cents here: using Java 8 Streams and 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));
}
}
I renamed the function to fromString()
since naming it using that convention, you'll obtain some benefits from Java language itself; for example:
Answered 2023-09-20 20:32:32
If you don't want to write your own utility, use Google's guava 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.
Answered 2023-09-20 20:32:32
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 the String method, it 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;
}
}
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 example, if you provide "PERSON" in the fromEnumName it'll return you the Value of Enum, i.e., "Person".
Answered 2023-09-20 20:32:32
Another way of doing this is by using the implicit static method name()
of Enum. name will return the exact string used to create that enum which can be used to check against the 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
Answered 2023-09-20 20:32:32
In Java 8 the static Map pattern is even easier and is my preferred 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);
}
}
Answered 2023-09-20 20:32:32
Here is a 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();
}
}
Answered 2023-09-20 20:32:32
Enum is very useful. I have been using Enum
a lot to add a description for some fields in different languages, as the following example:
public enum Status {
ACT(new String[] { "Accepted", "مقبول" }),
REJ(new String[] { "Rejected", "مرفوض" }),
PND(new String[] { "Pending", "في الانتظار" }),
ERR(new String[] { "Error", "خطأ" }),
SNT(new String[] { "Sent", "أرسلت" });
private String[] status;
public String getDescription(String lang) {
return lang.equals("en") ? status[0] : status[1];
}
Status(String[] status) {
this.status = status;
}
}
And then you can retrieve the description dynamically based in the language code passed to the getDescription(String lang)
method, for example:
String statusDescription = Status.valueOf("ACT").getDescription("en");
Answered 2023-09-20 20:32:32
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 and 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 information on avoiding null with Optional.
Answered 2023-09-20 20:32:32
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 Geoffrey Zheng's, but there isn't any need to roll your own when it's out there in the wild already.
Answered 2023-09-20 20:32:32
An O(1) method inspired from Thrift-generated code which uses 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;
}
}
Answered 2023-09-20 20:32:32
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;
}
Answered 2023-09-20 20:32:32
java.lang.Enum
defines several useful methods, which is available to all enumeration types in Java:
name()
method to get the name of any Enum constants. The string literal used to write enum constants is their name.values()
method can be used to get an array of all Enum constants from an Enum type.valueOf()
method to convert any String to an 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, the valueOf()
method returns an Enum constant, Gender.MALE, and calling name on that returns "MALE"
.
Answered 2023-09-20 20:32:32
Use:
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();
}
}
}
Answered 2023-09-20 20:32:32
Enum valueOf()
An enum class automatically gets a static valueOf() method in the class when compiled. The valueOf() method can be used to obtain an instance of the enum class for a given String value.
For example:
public class Main {
public static void main(String[] args) throws Exception {
System.out.println(Strings.TWO.name());
}
enum Strings {
ONE, TWO, THREE
}
}
Answered 2023-09-20 20:32:32
Adding on to Michael Myers' 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
}
Answered 2023-09-20 20:32:32
As a switch
-version has not been mentioned yet I introduce it (reusing OP's enum):
private enum Blah {
A, B, C, D;
public static Blah byName(String name) {
switch (name) {
case "A":
return A;
case "B":
return B;
case "C":
return C;
case "D":
return D;
default:
throw new IllegalArgumentException(
"No enum constant " + Blah.class.getCanonicalName() + "." + name);
}
}
}
Since this don't give any additional value to the valueOf(String name)
method, it only makes sense to define an additional method if we want have a different behavior. If we don't want to raise an IllegalArgumentException
we can change the implementation to:
private enum Blah {
A, B, C, D;
public static Blah valueOfOrDefault(String name, Blah defaultValue) {
switch (name) {
case "A":
return A;
case "B":
return B;
case "C":
return C;
case "D":
return D;
default:
if (defaultValue == null) {
throw new NullPointerException();
}
return defaultValue;
}
}
}
By providing a default value we keep the contract of Enum.valueOf(String name)
without throwing an IllegalArgumentException
in that manner that in no case null
is returned. Therefore we throw a NullPointerException
if the name is null
and in case of default
if defaultValue
is null
. That's how valueOfOrDefault
works.
This approach adopts the design of the Map
-Interface which provides a method Map.getOrDefault(Object key, V defaultValue)
as of Java 8.
Answered 2023-09-20 20:32:32
I was looking for an answer to find the "blah" name and not its value (not the text). Based on Manu's answer, I find this code useful:
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 valueOfCode(String blahCode) throws IllegalArgumentException {
Blah blah = Arrays.stream(Blah.values())
.filter(val -> val.name().equals(blahCode))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("Unable to resolve blah: " + blahCode));
return blah;
}
}
Answered 2023-09-20 20:32:32
public enum ToggleStatusUpdate {
OFF("off", 1),
ON("on", 2);
private final String name;
private final int position;
private ToggleStatusUpdate(String name, int position) {
this.name = name;
this.position = position;
}
public String getName() {
return name;
}
public int getPosition() {
return position;
}
public static int getPositionForName(String name) {
for(ToggleStatusUpdate toggleStatusUpdate : ToggleStatusUpdate.values()) {
if (toggleStatusUpdate.getName().equals(name)) {
return toggleStatusUpdate.getPosition();
}
}
return -1;
}
public static void main(String[] args) {
System.out.println(ToggleStatusUpdate.getPositionForName("off"));
}
}
Answered 2023-09-20 20:32:32
getPositionForName()
method is called we can create static Map holding name to Enum mapping. It will precompute the mapping and every method call will not iterate the enum values. As we are fetching it from map it is O(1) operation. - anyone 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")
.
Answered 2023-09-20 20:32:32
A combination of answers and comments for Java 8 using Streams. It creates a static Map for lookup with the opportunity of a default value, to prevent null checks.
public enum Blah {
A, B, C, D, INVALID
private static final Map<String, Blah> ENUM_MAP = Stream.of(Blah.values())
.collect(Collectors.toMap(Enum::name, Function.identity()));
public static Blah of(final String name) {
return ENUM_MAP.getOrDefault(name, INVALID);
}
}
// e.g.
Blah.of("A");
A
Blah.of("X")
INVALID
Answered 2023-09-20 20:32:32
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;
}
Answered 2023-09-20 20:32:32
Create an extension and then call valueOf<MyEnum>("value")
. If the type is invalid, you'll get null and have to handle it
inline fun <reified T : Enum<T>> valueOf(type: String): T? {
return try {
java.lang.Enum.valueOf(T::class.java, type)
} catch (e: Exception) {
null
}
}
Alternatively, you can set a default value, calling valueOf<MyEnum>("value", MyEnum.FALLBACK)
, and avoiding a null response. You can extend your specific enum to have the default be automatic
inline fun <reified T : Enum<T>> valueOf(type: String, default: T): T {
return try {
java.lang.Enum.valueOf(T::class.java, type)
} catch (e: Exception) {
default
}
}
Or if you want both, make the second:
inline fun <reified T : Enum<T>> valueOf(type: String, default: T): T = valueOf<T>(type) ?: default
Answered 2023-09-20 20:32:32