首先,有一个特定优化的Map 实现来保存枚举键:EnumMap。
不幸的是,Kotlin 标准库中没有方便的函数用于创建 EnumMap(就像其他 Map 实现一样),所以你可以定义自己的(感谢 @Adam Millerchip 的想法):
inline fun <reified K : kotlin.Enum<K>, V> enumMapOf() = EnumMap<K, V>(K::class.java)
inline fun <reified K : kotlin.Enum<K>, V> enumMapOf(vararg pairs: Pair<K, V>) = pairs.toMap(EnumMap(K::class.java))
其次,当原始列表中有两个地图具有相同的键(和不同的值)时,可能会有不同的策略来缓解这种情况:
val list = listOf(
mapOf(Enum.First to setOf("one", "two", "three")),
mapOf(Enum.Second to setOf("four", "five", "six")),
mapOf(Enum.First to setOf("four", "five", "six"))
)
简单的策略是“最新的胜利”:
val res = list.fold(enumMapOf<Enum, Set<String>>()) { acc, map ->
acc.apply { putAll(map) }
}
println(res) // {First=[four, five, six], Second=[four, five, six]}
另一种方法是“合并值”:
val resMerged = list.fold(enumMapOf<Enum, Set<String>>()) { acc, map ->
map.forEach { (k, v) -> acc.merge(k, v) { old, new -> old.union(new) } }
acc
}
println(resMerged) // {First=[one, two, three, four, five, six], Second=[four, five, six]}
为方便起见,您可以定义一个用于合并地图的辅助扩展方法(并将union 与中缀调用一起使用):
fun <K, V : Any> MutableMap<K, V>.merge(map: Map<K, V>, remappingFunction: (V, V) -> V) {
map.forEach { (k, v) -> this@merge.merge(k, v, remappingFunction) }
}
val resMerged = list.fold(enumMapOf<Enum, Set<String>>()) { acc, map ->
acc.apply { merge(map) { old, new -> old union new } }
}
println(resMerged) // {First=[one, two, three, four, five, six], Second=[four, five, six]}