Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Given java enum class, find enum by value

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.

like image 405
EarthTurtle Avatar asked Nov 05 '25 08:11

EarthTurtle


1 Answers

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.

This is not an issue: you can use EnumSet.allOf(Class) to access all enum values for a given enum Class. You can then use that like a normal Set, including streaming over it.

Optional<Animal> anAnimalThatMeows = 
    EnumSet
        .allOf(Animal.class)
        .stream()
        .filter(( Animal animal ) -> animal.getSound().equals("meow"))
        .findAny() ;

See this code run at Ideone.com.

like image 185
Louis Wasserman Avatar answered Nov 06 '25 21:11

Louis Wasserman



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!