kotlinenum-map

kotlin, how convert a EnumMap into regular Map


need to call a api which take Map<String, String>

fun api.log(map: Map<string, String>

but the key has to be only from the registered ones, so defined a enum for the registered keys:

enum class RegisteredKey {
    NONE, ZOOM
}

and first build the EnumMap<> to enforce key type:

var enumParamMap: EnumMap<RegisteredKey, String> = EnumMap<RegisteredKey, String>(RegisteredKey::class.java)
    enumParamMap.put(RegisteredKeys.NONE, "0")
    enumParamMap.put(RegisteredKeys.ZOOM, "1")

doLog(enumParamMap)

question 1, is there constructor to build the enumMap directly with data?

and then need to transform the EnumMap into a Map<> so that the api.log() will accept it

fun doLog(enumParamMap: EnumMap<RegisteredKey, String>) {

    val map: MutableMap<String, String> = mutableMapOf()

    for (enum in enumParamMap.entries) {
        map.put(enum.key.name, enum.value)
    }
    api.log(map)
}

question 2: is there simpler way to map the enumMap to regular map?


Solution

  • I'm not sure I'm interpreting your first question correctly, but if you mean you want to initialize an exhaustive EnumMap where every key has an entry, similar to the Array constructor that takes a lambda, you could write one like this:

    inline fun <reified K : Enum<K>, V> exhaustiveEnumMap(init: (key: K) -> V): EnumMap<K, V> {
        val map = EnumMap<K, V>(K::class.java)
        for (key in enumValues<K>())
            map[key] = init(key)
        return map;
    }
    

    Usage:

    val map = exhaustiveEnumMap<RegisteredKey, String> { key -> key.ordinal.toString() }
    

    or

    val map = exhaustiveEnumMap<RegisteredKey, String> { key -> 
        when (key){
            RegisteredKey.NONE -> "0"
            RegisteredKey.ZOOM -> "1"
        }
    }
    

    Edit based on your comment: You could do that by wrapping a mapOf call with the EnumMap constructor like this, but it would be instantiating an intermediate throwaway LinkedHashMap:

    val map = EnumMap(mapOf(RegisteredKey.NONE to "0", RegisteredKey.ZOOM to "1"))
    

    Instead, you could write a helper function like this:

    inline fun <reified K: Enum<K>, V> enumMapOf(vararg pairs: Pair<K, V>): EnumMap<K, V> =
        pairs.toMap(EnumMap<K, V>(K::class.java))
    

    Usage:

    var enumParamMap = enumMapOf(RegisteredKey.NONE to "0", RegisteredKey.ZOOM to "1")
    

    -------

    For your next question, I'm not sure if this is really any simpler, but you could do:

    fun doLog(enumParamMap: EnumMap<RegisteredKey, String>) =
        api.log(enumParamMap.map{ it.key.name to it.value }.toMap())
    

    It's more concise, but you're allocating a list and some pairs that you wouldn't be with your way of doing it.