在Scala中,List()和Nil之间是否存在_performance_差异?

时间:2014-11-04 10:10:14

标签: scala

假设我有一个接受对象和列表的函数:

case class Point(x: Int, y: Int)
def f1(w: Point, l: List[String]) =  { /* do something /* }

我通常会这样使用它:

val w = Point(1,1)
val lst = List("Hello", "world")
f1(w, lst) // non empty list

我需要多次调用带有空列表的函数作为第二个参数:

f1(w, List()) // empty list
f1(w, Nil) // empty list

最后两行之间是否有任何性能差异?

我认为使用List()会调用List.apply()方法。 Scala编译器是否将其优化为Nil

EDIT1

这不是Scala: Nil vs List()

的副本

注意:NilList()之间是否存在性能差异? Scala编译器在这里做了什么优化吗?

1 个答案:

答案 0 :(得分:7)

有这样的课程

import collections.immutable.List

class Test {
  val l = List() // or Nil
}

编译它们,然后用javap -v

检查生成的字节码

List()给出:

5: getstatic     #26                 // Field scala/collection/immutable/Nil$.MODULE$:Lscala/collection/immutable/Nil$;
8: putfield      #14                 // Field l:Lscala/collection/immutable/List;

Nil给出了:

5: getstatic     #24                 // Field scala/collection/immutable/Nil$.MODULE$:Lscala/collection/immutable/Nil$;
8: putfield      #13                 // Field l:Lscala/collection/immutable/Nil$;

因此,两者的字节码(和性能)是相同的。可能还有其他理由选择其中一个,如Govind在评论中链接的问题所述。

深入潜入兔子洞

查看源List()是List.apply()的糖,它是这样实现的:

def apply[A](xs: A*) = xs.toList

toList来自TraversableOnce,并调用to[List],其隐含地带有CanBuildFrom[Nothing, A, List[A]],在这种情况下为List.canBuildFrom,后者又来自ReusableCBF {1}},然后使用.apply()++= the empty array,然后build()

调用该构建器

如何将此消除/转换为getstatic List()对我来说是非常清楚的。 (或者我在途中错过了一些聪明的东西)。