Get Enum by Its Inner Field

Get enum by its inner field

You can use a static Map<Integer,TestEnum> with a static initializer that populates it with the TestEnum values keyed by their number fields.

Note that findByKey has been made static, and number has also been made final.

import java.util.*;

public enum TestEnum {
ONE(1), TWO(2), SIXTY_NINE(69);

private final int number;
TestEnum(int number) {
this.number = number;
}

private static final Map<Integer,TestEnum> map;
static {
map = new HashMap<Integer,TestEnum>();
for (TestEnum v : TestEnum.values()) {
map.put(v.number, v);
}
}
public static TestEnum findByKey(int i) {
return map.get(i);
}

public static void main(String[] args) {
System.out.println(TestEnum.findByKey(69)); // prints "SIXTY_NINE"

System.out.println(
TestEnum.values() == TestEnum.values()
); // prints "false"
}
}

You can now expect findByKey to be a O(1) operation.

References

  • JLS 8.7 Static initializers
  • JLS 8.9 Enums

Related questions

  • Static initalizer in Java
  • How to Initialise a static Map in Java

Note on values()

The second println statement in the main method is revealing: values() returns a newly allocated array with every invokation! The original O(N) solution could do a little better by only calling values() once and caching the array, but that solution would still be O(N) on average.

How to get the enum type by its attribute?

All you need to do is add a default case so the method always returns something or throws an exception:

AreaCode area(int n){
switch (n) {
case 7927: return AreaCode.area1;
case 7928: return AreaCode.area2;
case 7929: return AreaCode.area3;
default: return null;
}
}

or perhaps better

AreaCode area(int n){
switch (n) {
case 7927: return AreaCode.area1;
case 7928: return AreaCode.area2;
case 7929: return AreaCode.area3;
default: throw new IllegalArgumentException(String.valueOf(n));
}
}

Getting Enum value by another value

The ENUM types has the method values, which you can use to extract all the enum values and compare their identifier against the one that you have passed by the method parameter, namely:

public MyEnum getEnum(String identifier){
for(MyEnum e : MyEnum.values())
if(e.identifier.equals(identifier))
return e;
return null;
}

or even better:

public static Optional<MyEnum> getEnum(String identifier){
return Arrays.stream(MyEnum.values()).filter(i -> i.identifier.equals(identifier)).findFirst();
}

This way you make it clear on the method signature that you might or not find the enum.

Can I get an enum based on the value of its field?

For reference, here is an alternative solution with a HashMap:

enum CrimeCategory {
ASBO("Anti Social Behaviour"),
BURG("Burglary"),
CRIMDAM("Criminal Damage And Arson"),
DRUGS("Drugs"),
OTHTHEFT("Other Theft"),
PUPDISOR("Public Disorder And Weapons"),
ROBBERY("Robbery"),
SHOPLIF("Shoplifting"),
VEHICLE("Vehicle Crime"),
VIOLENT("Violent Crime"),
OTHER("Other Crime");

private static final Map<String, CrimeCategory> map = new HashMap<>(values().length, 1);

static {
for (CrimeCategory c : values()) map.put(c.category, c);
}

private final String category;

private CrimeCategory(String category) {
this.category = category;
}

public static CrimeCategory of(String name) {
CrimeCategory result = map.get(name);
if (result == null) {
throw new IllegalArgumentException("Invalid category name: " + name);
}
return result;
}
}

How to fetch value of an enum present in an inner class through Reflection

You're calling BET_TYPE_NAME.AllEven.toString() and it is implemented in the parent Enum class to return the same value as BET_TYPE_NAME.AllEven.name(), thus you get "AllEven".

To get "12", you either need to override the toString() inside the BET_TYPE_NAME enum like:

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

Or cast the result of Field.get(null) to the enum BET_TYPE_NAME and call getValue() on it:

return Integer.toString(((TwelveByTwentyFour.BET_TYPE_NAME)
Class.forName(Test.class.getCanonicalName()+"$"+gameName+"$"+"BET_TYPE_NAME")
.getDeclaredField(betType).get(null)).getValue());

BTW, the enum should never have a setter and the value should always be final — enum constants are shared singletons.

How can I lookup a Java enum from its String value?

Use the valueOf method which is automatically created for each Enum.

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

For arbitrary values start with:

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

Only move on later to Map implementation if your profiler tells you to.

I know it's iterating over all the values, but with only 3 enum values it's hardly worth any other effort, in fact unless you have a lot of values I wouldn't bother with a Map it'll be fast enough.

How to get an enum value from a string value in Java

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.

Get enum.values() from class that containing it

You can do Clazz.MyEnum.values() to access the Enum or you can directly import MyEnum in your other classes import com.in.Clazz.MyEnum becuase MyEnum is public.

To get MyEnum constant via reflection, but if MyEnum is accessible then there is no need to use reflection. You can do it in following way,

Class<?> clazz = Clazz.class;//You are getting dynamically
Class<?> enumClass = clazz.getDeclaredClasses()[0];//assuming at index 0
Enum<?>[] enumConstants = (Enum<?>[]) enumClass.getEnumConstants();
System.out.println(enumConstants[0]);

OUTPUT

Hello

Inner class for each member of enum?

One think you could do instead is have your enum implement Supplier<Context>. Now each item would have to declare a get() method to create the individual Context sub type.

enum MyEnum implements Supplier<Context>{
FOO{ @Override public Context get(){ return new FooContext(); } },
BAR{ @Override public Context get(){ return new BarContext(); } }
}

which would make your client code much simpler:

private void handleType (MyEnum type) {
handleContext(type.get());
}

How to iterate over an enum that has custom values?

Use a stream to map an array of enum values to a list of strings.

List<String> exercises = Stream.of(DaysOfExercise.values())
.map(DaysOfExercise::getExercise)
.collect(Collectors.toList());


Related Topics



Leave a reply



Submit