Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin: How to check if enum contains a given String without messing with Exceptions?

Tags:

kotlin

Why there is no contains method in enum classes (as well as in Java)? And how to implement it elegantly? Now I'm using this ugly approach:

val contains: Boolean = 
    try {
        MyEnum.valueOf("some string")
        true
    } catch (e: IllegalArgumentException) {
        false
    }
like image 822
Maksim Ostrovidov Avatar asked Jan 25 '17 05:01

Maksim Ostrovidov


3 Answers

enumContains

You can create an enumContains function similar to Hound Dog's answer but using reified type parameters instead.

You cannot create a JVM independent solution in Kotlin 1.0 but you can in Kotlin 1.1 using enumValues.

Kotlin 1.1

/**
 * Returns `true` if enum T contains an entry with the specified name.
 */
inline fun <reified T : Enum<T>> enumContains(name: String): Boolean {
    return enumValues<T>().any { it.name == name}
}

Kotlin 1.0

/**
 * Returns `true` if enum T contains an entry with the specified name.
 */
inline fun <reified T : Enum<T>> enumContains(name: String): Boolean {
    return T::class.java.enumConstants.any { it.name == name}
}

Usage

enumContains<MyEnum>("some string") // returns true or false

enumValueOfOrNull

If you also need the actual enum entry then you might consider creating an enumValueOfOrNull function instead.

Kotlin 1.1

/**
 * Returns an enum entry with the specified name or `null` if no such entry was found.
 */
inline fun <reified T : Enum<T>> enumValueOfOrNull(name: String): T? {
    return enumValues<T>().find { it.name == name }
}

Kotlin 1.0

/**
 * Returns an enum entry with the specified name or `null` if no such entry was found.
 */
inline fun <reified T : Enum<T>> enumValueOfOrNull(name: String): T? {
    return T::class.java.enumConstants.find { it.name == name }
}

Usage

enumValueOfOrNull<MyEnum>("some string")
like image 167
mfulton26 Avatar answered Nov 17 '22 04:11

mfulton26


You can just take values Array of your enum and use contains over it. For example:

Planets.values().map { it.name }.contains("EARTH")

But for this you need to have correct string value so you might uppercase it before search.

If you want to find enum by its value take a look at the Reverse Lookup for enums.

Edit:

As @JamesBassett suggested you can optimize it to stop looking once it finds a match.

Planets.values().any { it.name == "EARTH" }
like image 18
Januson Avatar answered Nov 17 '22 05:11

Januson


You could do something like this:

fun <T : Enum<*>> KClass<T>.contains(value: String): Boolean {
    return this.java.enumConstants.any { it.name == value }
}

MyEnum::class.contains("some string")
like image 3
James Bassett Avatar answered Nov 17 '22 06:11

James Bassett