在一个班轮中,对 listOf() 为 null,对 Kotlin 中的 listOf(value) 不为 null?

null to listOf(), not null to listOf(value) in Kotlin in one liner?

f() return 一个可为 null 的值。

我想做的是
如果 f() 为空,得到一个空列表,
否则,如果 f() 不为空,则获取单个项目的列表 value.

在 Scala 中,我们可以这样做:

Option(f()).toList

或更详细

Option(f()).map(v => List(v)).getOrElse(List.empty)

在 Kotlin 中,没有 Option(假设没有 Funktionale 库),并且 null 没有 toList(),这与 Scala 中的 (None: Option) 不同。

我们有 Elvis 运算符,但 null 将在 listOf() 函数内,因此它将是

listOf(f() ?: /* What can I do here? */)

我们想要的null是listOf(/*no argument */),但是Elvis运算符需要一个参数,所以listOf(f() ?: )会导致编译错误。

至少我们可以做到

val v = f()
if (v == null) listOf() else listOf(v)

但它是两个班轮。

有什么表达方式吗?

我将在 class 的主要构造函数默认参数中使用此表达式,因此如果它不是一个衬里,它将被括在括号中,所以像这样:

class A(
    val p1: List<V> = run {
        val v = f()
        if (v == null) listOf() else listOf(v)
    },
    val p2: ... = ...,
    ...)

这看起来很丑,不是吗?

编辑

正如@Naetmul 指出的那样,listOfNotNull(f()) 在语法上比我最初在下面发布的内容更好,并且还采用可变数量的参数,例如

val myList = listOfNotNull(f(), g(), h())

将 return 列出所有不为空的结果。


我会在这里使用let

val myList = f()?.let { listOf(it) } ?: emptyList()

使用 ?. safe call on the return value of f(), then use let to run a code block. If f() is null, it won't run this block of code, resulting in a null value. Then we use the ?: elvis operator 回退到空列表。

这里分成几行方便理解

val myValue = f()
val myList: List<Any>
if (myValue != null) {
    myList = listOf(myValue)
} else {
    myList = emptyList()
}

对于这个具体问题,我可以做到

listOfNotNull(f())