A common desire in my project is to find an enum when given one of its constructed values. For example:
public enum Animal {
DOG("bark"),
CAT("meow");
public final String sound;
Animal(String sound) {
this.sound = sound;
}
public String getSound() {
return sound;
}
}
If given the string "meow"
, I want to get a CAT
The easy solution is to write a search method that iterates over the values of the Enum
public static Animal getBySound(String sound) {
for(Animal e : values()){
if(e.sound.equals(sound)){
return e;
}
}
}
But this has to be done individually, for every enum defined. Is there a way, given an Enum class and a method that gets a field's value, you can get the enum who's specified field matches the input?
Possible signature:
public static <T extends Enum<T>, V> Optional<T> findEnumByValue(Class<T> enumClass, Function<T, V> fieldGetter, V valueToMatch)
The closest I've gotten is this, but having the first argument be Enum[]
is just one step away from being fully type-safe (as the method could be supplied an arbitrary array of enums)
public static <T extends Enum<T>, V> Optional<T> findEnumByValue(T[] enums, Function<T, V> fieldGetter, V valueMatch) {
return Arrays.stream(enums).filter(element -> Objects.equals(fieldGetter.apply(element), valueMatch)).findFirst();
}
// Example usage
Animal animal = findEnumByValue(Animal.values(), Animal::getSound, "meow").orElse(CAT);
It seems that part of the difficulty is that the static method values()
that is a part of every Enum class is not accessible through the Class
object.