这是我想编写的Kotlin代码(为清晰起见,带有额外的类型注释:]
fun test(alpha: String, beta: String, gamma: String? = null, delta: String? = null) {
val r1: Map<String, String?> =
hashMapOf(
"alpha" to alpha,
"beta" to beta,
"gamma" to gamma,
"delta" to delta
)
val r2: Map<String, String> = r1.filterValues { it != null }
callSomeFunction(r2) // expects a parameter of type Map<String, String>
}
[不幸的是,r1.filterValues { it != null }
给了我一个Map<String, String?>
,而不是Map<String, String>
。我明白为什么会这样;这也是listOf(1, null).filter { it != null }
与listOf(1, null).filterNotNull()
具有不同类型的原因。但是,我仍然需要解决我的问题!
是否有从Map
到“ filterValuesNotNull”的惯用方式?
或者提高级别,还有其他惯用的方式说“给我以下参数的Map
,但跳过那些值为空的参数”吗?我可以求助于this,但我不想:
fun test(alpha: String, beta: String, gamma: String? = null, delta: String? = null) {
var r1: MutableMap<String, String> = mutableMapOf(
"alpha" to alpha,
"beta" to beta
)
if (gamma != null) {
r1["gamma"] = gamma
}
if (delta != null) {
r1["delta"] = delta
}
callSomeFunction(r1) // expects a parameter of type Map<String, String>
}
这里有两种方法,尽管我都不知道这两种方法是否惯用。
@Suppress("UNCHECKED_CAST)
fun filterNotNullUnchecked(map: Map<String, String?>): Map<String, String> =
map.filterValues { it != null } as Map<String, String>
编辑:正如@ Tenfour04指出的那样,这并不安全,只是由于类型擦除而未选中,而添加Suppress("UNCHECKED_CAST)
注释会使警告消失。
fun filterNotNullUgly(map: Map<String, String?>): Map<String, String> {
val map2 = HashMap<String, String>()
for ((k, v) in map) if (v != null) map2[k] = v
return map2
}
嗯,我想,可以这样决定
val newMap: Map<String, String> = r1.mapNotNull { (key, value) ->
value?.let { key to it }
}.toMap()
我认为应该在stdlib中的功能:
fun <K,V: Any> Map<K,V?>.filterNotNullValuesTo(destination: MutableMap<K,V>): Map<K, V> {
for ((key, value) in entries) if (value != null) destination[key] = value
return destination
}
fun <K,V: Any> Map<K,V?>.filterNotNullValues(): Map<K,V> = filterNotNullValuesTo(mutableMapOf())