Kotlin反向查找有效的枚举?

我试图找到在Kotlin的枚举上进行“反向查找”的最佳方法。 Effective Java中的一个例子是你在枚举中引入了一个静态映射来处理反向查找。 通过一个简单的枚举将其移交给Kotlin,将使我看起来像这样的代码:

enum class Type(val value: Int) { A(1), B(2), C(3); companion object { val map: MutableMap<Int, Type> = HashMap() init { for (i in Type.values()) { map[i.value] = i } } fun fromInt(type: Int?): Type? { return map[type] } } } 

我的问题是,这是做这件事的最好方法,还是有更好的办法? 如果我有几个枚举遵循类似的模式呢? Kotlin有没有办法让这个代码在枚举中更加可重用?

首先,fromInt()的参数应该是一个Int,而不是Int ?. 试图获得一个类型使用null显然会导致null,并且调用者甚至不应该尝试这样做。 地图也没有理由是可变的。 代码可以减少到

 companion object { private val map = Type.values().associateBy(Type::value); fun fromInt(type: Int) = map[type] } 

这段代码太短了,坦率地说,我不确定值得找到一个可重用的解决方案。

在这种情况下,这没什么意义,但是这里是@ JBNized解决方案的“逻辑提取”

 open class EnumCompanion<T, V>(private val valueMap: Map<T, V>) { fun fromInt(type: T) = valueMap[type] } enum class TT(val x: Int) { A(10), B(20), C(30); companion object : EnumCompanion<Int, TT>(TT.values().associateBy(TT::x)) } //sorry I had to rename things for sanity 

一般来说,这是关于伴侣对象的事情,它们可以被重用(与Java类中的静态成员不同)

我发现自己通过自定义,手工编码,价值几次进行反向查找,并采用以下方法。

使enum实现一个共享的接口:

 interface Codified<out T : Serializable> { val code: T } enum class Alphabet(val value: Int) : Codified<Int> { A(1), B(2), C(3); override val code = value } 

这个接口(不过奇怪的名字是:))标记为显式代码的某个值。 目标是能够写:

 val a = Alphabet::class.decode(1) //Alphabet.A val d = Alphabet::class.tryDecode(4) //null 

用下面的代码可以轻松实现:

 interface Codified<out T : Serializable> { val code: T object Enums { private val enumCodesByClass = ConcurrentHashMap<Class<*>, Map<Serializable, Enum<*>>>() inline fun <reified T, TCode : Serializable> decode(code: TCode): T where T : Codified<TCode>, T : Enum<*> { return decode(T::class.java, code) } fun <T, TCode : Serializable> decode(enumClass: Class<T>, code: TCode): T where T : Codified<TCode> { return tryDecode(enumClass, code) ?: throw IllegalArgumentException("No $enumClass value with code == $code") } inline fun <reified T, TCode : Serializable> tryDecode(code: TCode): T? where T : Codified<TCode> { return tryDecode(T::class.java, code) } @Suppress("UNCHECKED_CAST") fun <T, TCode : Serializable> tryDecode(enumClass: Class<T>, code: TCode): T? where T : Codified<TCode> { val valuesForEnumClass = enumCodesByClass.getOrPut(enumClass as Class<Enum<*>>, { enumClass.enumConstants.associateBy { (it as T).code } }) return valuesForEnumClass[code] as T? } } } fun <T, TCode> KClass<T>.decode(code: TCode): T where T : Codified<TCode>, T : Enum<T>, TCode : Serializable = Codified.Enums.decode(java, code) fun <T, TCode> KClass<T>.tryDecode(code: TCode): T? where T : Codified<TCode>, T : Enum<T>, TCode : Serializable = Codified.Enums.tryDecode(java, code) 

val t = Type.values()[序号]

🙂

我们可以使用find 返回匹配给定谓词的第一个元素,如果没有 find这个元素 ,则返回null。

 companion object { fun valueOf(value: Int): Type? = Type.values().find { it.value == value } }