有没有办法过滤掉null Any?Kotlin地图中的值?

Har*_*y J 9 collections kotlin

我试图想出一个函数,它允许通过应用单个函数将Map<String, Any?>对象视为Map<String,Any>通过类型推断.

我非常新在科特林转变职能,并且试图将各种filterfilterValues filterNot地图,像这样的:

val input = mapOf(Pair("first",null))
val filtered: Map<String,Any> = input.filter { it.value!=null }
Run Code Online (Sandbox Code Playgroud)

它也无法编译任何这些

input.filterValues { it!=null }
input.filterNot { it.value==null }
input.filterNot { it.value is Nothing }
Run Code Online (Sandbox Code Playgroud)

我似乎最接近的是应用多个步骤或具有未选中的强制转换警告.我本以为过滤这些值!=null就足够了.我唯一的另一个想法是,这是由于泛型?

hot*_*key 8

编译器只是不进行足够深入的类型分析来推断,例如,从地图中input.filterValues { it != null }过滤掉null值,因此结果映射应该具有非空值类型.基本上,在类型和可空性方面,可以存在具有任意含义的任意谓词.

没有特殊情况函数可以过滤nullstdlib中的映射值(就像.filterIsInstance<T>()迭代一样).因此,最简单的解决方案是应用未经检查的强制转换,从而告诉编译器您确定不违反类型安全性:

@Suppress("UNCHECKED_CAST")
fun <K, V> Map<K, V?>.filterNotNullValues() = filterValues { it != null } as Map<K, V>
Run Code Online (Sandbox Code Playgroud)

另请参阅:关于-check 的类似问题的另一个问题is.


JB *_*zet 8

过滤器函数返回一个与原始地图具有相同泛型类型的Map.要转换值的类型,您需要映射Any的值吗?做任何,通过做演员.编译器无法知道您传递给filter()的谓词确保过滤后的映射的所有值都是非空的,因此它不能使用类型推断.所以你最好的是使用

val filtered: Map<String, Any> = map.filterValues { it != null }.mapValues { it -> it.value as Any }
Run Code Online (Sandbox Code Playgroud)

或者定义一个函数在一次传递中进行过滤和转换,从而能够使用智能强制转换:

fun filterNotNullValues(map: Map<String, Any?>): Map<String, Any> {
    val result = LinkedHashMap<String, Any>()
    for ((key, value) in map) {
        if (value != null) result[key] = value
    }
    return result
}
Run Code Online (Sandbox Code Playgroud)