Get enum constant using its value

10,119

Solution 1

The valueOf method takes a string that should correspond the name of the enum constant. However, you extract the value of the enum and try to map that back to a constant. This does not work unless the value is equal to the name of the constant.

So your problem is that TaskAction.UN_FLAG.value returns "Un flag". Then you call TaskAction.valueOf("Un flag"), which cannot find any enum constant with the string you provided (because the name of the enum constant is UN_FLAG).

So basically: "Un flag" != "UN_FLAG"

Edit:

To fix the issue, I would create a function that finds the correct enum based on the value. I would place the function within the companion object of TaskAction. Like this:

companion object {
  fun from(s: String): TaskAction? = values().find { it.value == s }
}

Solution 2

I changed my enum class to something like below, I added a static Map. Because there is no way it maps the value and name by itself. I thought this may help some.

    enum class TaskAction constructor(val value: String) {
    ARCHIVE("Archive"), UN_FLAG("Un flag"), FLAG("Flag"), REDO("Redo"),
    READY("Ready"), EDIT("Edit"), DND("dnd"), DELETE("Delete"),
    IN_PROGRESS("In progress"), DONE("Done");

    companion object {
        private val lookup = HashMap<String, TaskAction>()

        init {
            TaskAction.values().map { lookup.put(it.value, it) }
        }

        fun getFromValue(value: String):TaskAction {
            return lookup[value]!!
        }
    }
}

Update:

Thank to @mfulton26 i simplified my code:

enum class TaskAction constructor(val value: String) {
    ARCHIVE("Archive"), UN_FLAG("Un flag"), FLAG("Flag"), REDO("Redo"),
    READY("Ready"), EDIT("Edit"), DND("dnd"), DELETE("Delete"),
    IN_PROGRESS("In progress"), DONE("Done");

    companion object {
        private val lookup = values().associateBy(TaskAction::value)
        fun fromValue(value: String):TaskAction = requireNotNull(lookup[value]) { "No TaskAction with value $value" }
    }
}

I even reduce the code to with the help of @marstran:

companion object {
    fun from(search: String): TaskAction =  requireNotNull(values().find { it.value == search }) { "No TaskAction with value $search" }
}
Share:
10,119
Sai
Author by

Sai

Six years of tech industry experience, an expert in Android application development and experience as a software solutions architect. Published 40+ app to PlayStore.

Updated on July 28, 2022

Comments

  • Sai
    Sai almost 2 years

    Im trying to get enum using its value but it throws an error saying No enum constant. The eg code is in Kotlin but it is same in Java Thanks in advance.

    import java.util.*
    
    enum class TaskAction constructor(val value: String) {
        ARCHIVE("Archive"), UN_FLAG("Un flag"), FLAG("Flag"), REDO("Redo"),
        READY("Ready"), EDIT("Edit"), DND("dnd"), DELETE("Delete"),
        IN_PROGRESS("In progress"), DONE("Done");
    }
    
    
    fun main(args: Array<String>) {
        showSomeThing(TaskAction.UN_FLAG.value)
    }
    
    fun showSomeThing(enum: String) {
        println(TaskAction.valueOf(enum))
    }
    

    Log:

    Exception in thread "main" java.lang.IllegalArgumentException: No enum constant TaskAction.Un flag

  • Sai
    Sai over 7 years
    Thank @marstran I know "Un flag" != "UN_FLAG". I'm seeking for solution not explanation.
  • marstran
    marstran over 7 years
    @SaiKiran See edit.
  • mfulton26
    mfulton26 over 7 years
    1. fromValue might be a better name than getFromValue. 2. lookup can be initialized simply as private val lookup = values().associateBy(TaskAction::value). 3. You might want to throw an IllegalArgumentException instead of a KotlinNullPointerException. e.g. return requireNotNull(lookup[value]) { "No TaskAction with value $value" }.