收集以跳过空值的映射

时间:2018-03-18 10:29:41

标签: kotlin

如何从列表中收集地图,其中排除/跳过空值?

此代码不会跳过空值:

val map = listOf(Pair("a", 1), Pair("b", null), Pair("c", 3), Pair("d", null))
    .associateBy({ it.first }, { it.second })
println(map)

解决方案解决方案。但收集到可变的地图:

val map2 = listOf(Pair("a", 1), Pair("b", null), Pair("c", 3), Pair("d", null))
    .mapNotNull {
        if (it.second != null) it else null
    }.toMap()    
println(map2)

那么有更方便的方法吗?另外,我想获得Map<String, Int>类型,而不是Map<String, Int?>

3 个答案:

答案 0 :(得分:5)

实际上,对pwolaq的回答略有改动,保证第二项不可为空:

val map = listOf(Pair("a", 1), Pair("b", null), Pair("c", 3), Pair("d", null))
    .mapNotNull { p -> p.second?.let { Pair(p.first, it) } }
    .toMap()
println(map)

这将为您提供Map<String, Int>,因为mapNotNull会忽略映射到null的任何内容,而let使用安全调用运算符?.会返回null如果其接收者(p.second)是null

这基本上就是您在问题中所说的内容,使用let更短。

“收集成可变地图”是什么意思?

答案 1 :(得分:3)

您想要过滤掉null值,然后您应该使用filter方法:

val map = listOf(Pair("a", 1), Pair("b", null), Pair("c", 3), Pair("d", null))
    .filter { it.second != null }
    .toMap()
println(map)

答案 2 :(得分:0)

一个更具可读性的解决方案可能是将associateBy函数与双爆炸表达式(!!)结合使用:

val map: Map<String, Int> = listOf(
        Pair("a", 1),
        Pair("b", null),
        Pair("c", 3),
        Pair("d", null)
)
.filter { it.first != null && it.second != null }
.associateBy({ it.first!! }, { it.second!! })

println(map)