有没有办法过滤掉null Any?KotlinMap中的值?

von4xj4u  于 2023-06-24  发布在  Kotlin
关注(0)|答案(4)|浏览(117)

我正在尝试考虑一个函数,它允许通过应用单个函数进行类型推断,将Map<String, Any?>对象视为Map<String,Any>
我对Kotlin中的转换函数非常陌生,并且在Map上尝试了各种filterfilterValuesfilterNot

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

它也无法编译任何这些

input.filterValues { it!=null }
input.filterNot { it.value==null }
input.filterNot { it.value is Nothing }

最接近我似乎可以得到的是应用多个步骤或有一个未检查的铸造警告。我认为将值过滤为!=null就足够了。我唯一的其他想法是,这是由于泛型?

1aaf6o9v

1aaf6o9v1#

过滤器函数返回的Map与原始Map具有相同的泛型类型。要转换值的类型,需要将值从Any?到任何人,通过做一个演员。编译器无法知道传递给filter()的 predicate 确保过滤Map的所有值都是非空的,因此它无法使用类型推断。所以你最好的et就是用

val filtered: Map<String, Any> = map.filterValues { it != null }.mapValues { it -> it.value as Any }

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

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

ymzxtsji2#

编译器只是没有执行足够深的类型分析来推断,例如,input.filterValues { it != null }从Map中过滤掉null值,因此结果Map应该具有非空值类型。基本上可以有任意 predicate ,其在类型和可空性方面具有任意含义。
在stdlib中,没有特殊情况的函数可以过滤出map中的null值(就像有.filterIsInstance<T>()用于可迭代对象)。因此,最简单的解决方案是应用一个未检查的强制转换,从而告诉编译器您确定没有违反类型安全:

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

另请参阅:another question with a similar problem about is-check。

9wbgstp7

9wbgstp73#

这不会产生任何警告kotlin 1.5.30

listOfNotNull(
        nullableString?.let { "key1" to it },
        nullableString?.let { "key2" to it }
    ).toMap()
qvtsj1bj

qvtsj1bj4#

变换单线滤波器

map.mapNotNull { (key, value) -> value?.let { key to value } }

相关问题