我尝试使用table = Map<K, V>
映射f: (K) -> M?
的键并获得Map<M, V>
。但是,我所有的尝试都有点臭:
table.mapKeys{ f(it.key) }.filter{it != null} as Map<M, V>
似乎最直接,但必须手动从Map<M?, V>
投射到Map<M, V>
。未经检查的演员回避了空检查&#34;生态系统&#34;,这似乎是关闭的(并导致IDE发出抱怨)。
table.filterKeys(f(it) != null).mapKeys(f)
很简单,但适用f
两次,感觉很愚蠢。
我也考虑过table.mapNotNull { f(it.key)?.let {res -> res to it.value} }.toMap()
,但创建中间列表非常缺乏吸引力。
我觉得应该有一种直截了当的声明(即没有MutableMap
)方式来实现这种转变,但我无法找到它。
答案 0 :(得分:3)
您可以为自己添加实用程序功能:
inline fun <K, V, R : Any> Map<K, V>.mapKeysNotNull(transform: (Map.Entry<K, V>) -> R?): Map<R, V> {
return mapKeysNotNullTo(LinkedHashMap(), transform)
}
inline fun <K, V, R : Any> Map<K, V>.mapKeysNotNullTo(destination: MutableMap<R, V>, transform: (Map.Entry<K, V>) -> R?): Map<R, V> {
forEach { element -> transform(element)?.let { destination.put(it, element.value) } }
return destination
}
这是此代码的长版本,以尽可能地匹配标准库集合扩展实现的样式。您可以根据需要简化此操作,例如:
inline fun <K, V, R : Any> Map<K, V>.mapKeysNotNull(transform: (Map.Entry<K, V>) -> R?): Map<R, V> {
val destination = LinkedHashMap<R, V>()
forEach { element -> transform(element)?.let { destination.put(it, element.value) } }
return destination
}
无论哪种方式,你尝试制作的电话都是这样的:
table.mapKeysNotNull(f)