【问题标题】:kotlin, how convert a EnumMap into regular Mapkotlin,如何将 EnumMap 转换为常规 Map
【发布时间】:2019-10-09 14:26:06
【问题描述】:

需要调用一个接受Map<String, String>的api

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

但密钥只能来自已注册的密钥,因此为已注册的密钥定义了一个枚举:

enum class RegisteredKey {
    NONE, ZOOM
}

并首先构建 EnumMap 以强制执行键类型:

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

doLog(enumParamMap)

问题一,有没有构造函数可以直接用数据构建enumMap?

然后需要将 EnumMap 转换为 Map 以便 api.log() 接受它

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)
}

问题 2:有没有更简单的方法将 enumMap 映射到常规映射?

【问题讨论】:

  • 您的问题 2 具有误导性,因为您不仅想要“常规地图”,而且想要具有与原始地图不同的参数的地图(您希望密钥的类型为 String 而不是 RegisteredKey) .

标签: kotlin enum-map


【解决方案1】:

我不确定我是否正确解释了您的第一个问题,但如果您的意思是要初始化一个详尽的 EnumMap,其中每个键都有一个条目,类似于采用 lambda 的 Array 构造函数,您可以编写一个类似这个:

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;
}

用法:

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

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

根据您的评论进行编辑:您可以通过像这样使用 EnumMap 构造函数包装 mapOf 调用来做到这一点,但它会实例化一个中间一次性 LinkedHashMap:

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

相反,您可以编写一个这样的辅助函数:

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

用法:

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

-------

对于您的下一个问题,我不确定这是否真的更简单,但您可以这样做:

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

它更简洁,但是你分配了一个列表和一些你不会用你的方式做的对。

【讨论】:

  • 对于第一个我的意思是像实例化一个常规地图它可以用 Map() {"a" to "1", "b" to "2"}跨度>
  • 有人评论了在另一个答案上转换地图的更好方法。 fun doLog(enumParamMap: EnumMap&lt;RegisteredKey, String&gt;) = api.log(enumParamMap.mapKeys{ it.key.name })
【解决方案2】:

这样的东西应该适用于初始化:

EnumMap<RegisteredKey, String>(
    mapOf(RegisteredKey.NONE to "0", RegisteredKey.ZOOM to "1")
)

要获得法线贴图,只需调用.toMutableMap():

EnumMap<RegisteredKey, String>(
    mapOf(RegisteredKey.NONE to "0", RegisteredKey.ZOOM to "1")
).toMutableMap()

【讨论】:

  • 这不太一样; OP 想要一个 Map 但你给了他们一个 Map。公平地说,OP 误导你说他们想要一张“法线贴图”,而实际上他们想要一张具有不同参数的贴图。
  • 使用.mapKeys {it.key.name} 而不是.toMutableMap()
猜你喜欢
  • 2016-10-31
  • 1970-01-01
  • 1970-01-01
  • 2020-01-16
  • 1970-01-01
  • 1970-01-01
  • 2020-04-01
  • 1970-01-01
  • 2017-08-22
相关资源
最近更新 更多