kotlin中emptyList的功能是什么?

wil*_*aya 2 android kotlin

为什么Kotlin中有这样的emptyList构造函数?它是一个不可变的List,所以没有办法添加或删除它的元素,它是空的!那么,这个emptyList的功能是什么?

mie*_*sol 11

emptyList不是一个构造函数,但返回的功能和不可变空列表实现.

存在这种功能的主要原因是节省分配.因为每次调用它都会emptyList返回相同的单例实例,因此可以无分配地使用它.请注意,无论元素类型emptyList<String>() === emptyList<Int>()是什么,都会返回相同的对象true.

恕我直言emptyList也比listOf用作例如默认参数值时读得更好:

data class Person(val friends:List<Person> = emptyList())
Run Code Online (Sandbox Code Playgroud)

  • 它必须是一个函数(而不是直接暴露底层单例对象实例)的原因是它不能是通用的:你想对空字符串列表和空BigDecimal列表使用相同的实例.这是有效的,因为你永远不会从空列表中获取任何对象,因此它是完全类型安全的. (2认同)

Nic*_*ler 7

@miensol 提供了一个很好的答案,解决了使用单例空列表对象的较低级别的细节,最大限度地减少了分配。在我看来,在基于 JVM 的语言中分配空列表的意义不大。通过实例化时,您将丢失几个字节的内存或仅浪费几个时钟周期listOf()。当然,如果您一直创建空列表,这可能会增加,但我很难看出这适用于哪里。

虽然我不知道 API 的设计意图,但我确实看到了包含它的语义原因。正如 @miensol 已经指出的那样,emptyList()似乎是默认参数的良好候选者。这是真的,因为它遵循众所周知的空对象模式

简而言之,该模式建议我们使用语义上有意义的类型来表示空值、默认值或 null 值。在容易受到空指针异常影响的语言中,这很有用,因为适当的对象允许客户端调用任何可用的类成员。

考虑下面的示例,其中我们使用默认值null.

class AcademicProfile(val courseGradesAsPercent : List<Double>? = null) {

    fun displayAverage() {
        if (courseGradesAsPercent == null)
            println("No average to calculate, please sign-up for a course!")
        else {
            val sum = courseGradesAsPercent.reduce { accumulator, value -> accumulator + value }
            val average = sum / courseGradesAsPercent.count()
            println("Your unweighted average is $average")
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

该类表达的意图是课程成绩列表可以处于以下任何状态:

  • 无效的
  • 不为空,但为空
  • 充满元素

现在,假设我们使用emptyList()默认值:

class AcademicProfile(val courseGradesAsPercent : List<Double> = emptyList()) {

    fun displayAverage() {
        if (courseGradesAsPercent.isEmpty())
            println("No average to calculate, please sign-up for a course!")
        else {
            val sum = courseGradesAsPercent.reduce { accumulator, value -> accumulator + value }
            val average = sum / courseGradesAsPercent.count()
            println("Your unweighted average is $average")
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,和empty之间不会产生混淆null。如果没有成绩,则列表为空。这些语义通过允许我们调用空对象类型(即List<Double>.isEmpty())的成员而被带入函数中。使用null较少表达有关领域的信息,而是依赖于语言的机制。

使用单例空列表的性能优势只是锦上添花!


Ale*_*nov 6

讲话

其实我想知道为什么人们使用emptyList?做什么的?

更直接:您需要它,例如传递给采用列表的方法,或者当您的代码的一个分支中有一个列表为空而不是另一个分支时:

val commandLineOptions: List<String> = when {
    x > 0 -> listOf(...)
    else -> emptyList()
}

runCommand(command, commandLineOptions)
Run Code Online (Sandbox Code Playgroud)