【问题标题】:How do I map non-null elements without an assertion in Kotlin?如何在 Kotlin 中映射没有断言的非空元素?
【发布时间】:2021-05-27 21:43:01
【问题描述】:

我正在尝试找到更好的方法来链接 Kotlin 中的 filtermap 运算符。我想要做的是在转到map 运算符之前过滤空项目。

我能够链接它们,但编译器抱怨我的列表项的可空性。

class Person(val age : String?)

fun foo(age :String){
    // require non-null age
}

示例用法为:

val list = mutableListOf(Person("3"), Person("2"))

list.filter{ it.age != null }.map{ foo(it.age) }
// The IDE wants me to add !!

那么为什么 Kotlin 不能推断可空性?向下传递给 map 的已过滤(所有非 null)项应已过滤以确保它们为非 null。

【问题讨论】:

    标签: kotlin


    【解决方案1】:

    您可以将filtermap 替换为一种方法mapNotNull

    val list2 = list.mapNotNull { it.age }
    

    【讨论】:

    • 感谢您指出这一点!这正是我要找的。​​span>
    【解决方案2】:

    这种情况对人类来说似乎很容易,但从技术上讲,编译器很难理解过滤后它是一个 people 对象列表,但 age 属性的类型与原始类型不同.

    如果您不在map() 阶段使用整个people 实例,那么我认为最简单的做法是:

    list
        .mapNotNull { it.age }
        .map(::foo)
    

    或者,如果您的 foo() 不能返回空值:

    list.mapNotNull { it.age?.let(::foo) }
    

    但我认为这不太可读。或者你可以直接使用!! - 如果我们知道我们在做什么,那就没那么糟糕了。

    【讨论】:

      【解决方案3】:

      您可以在此处使用Iterable<T>.filterNotNull() 扩展函数,它将返回一个不可为空类型的列表。

      在您的情况下,编译器还不够先进,无法对过滤后的列表进行智能转换,这将是很多问题。因此,如果您需要专门使用filter,则必须添加一个断言。

      【讨论】:

        猜你喜欢
        • 2017-11-03
        • 2021-03-11
        • 2018-08-06
        • 1970-01-01
        • 2021-07-21
        • 2020-08-05
        • 2018-09-22
        • 2022-11-22
        • 1970-01-01
        相关资源
        最近更新 更多