Scala List链式cons运算符vs List构造函数

时间:2017-08-23 19:45:17

标签: scala

两个List构造在编译/内存占用方面是否相同?

val list1 = x1 :: x2 :: x3 :: Nil
val list2 = List(x1, x2, x3)

我认为list1代价更高,因为每个h :: t创建一个List,然后将每个新元素连接起来(产生一个新列表)直到最终列表。虽然list2一次创建了一个列表。

2 个答案:

答案 0 :(得分:7)

我认为,第一个更有效:它实际上从右到左,并且将元素添加到列表实际上非常便宜,就像创建案例类的新实例一样便宜:{{1} }

另一种方式实际上是一个varargs调用,因此,它首先创建一个新数组,并将所有变量放在那里,然后将其包装到def ::(x: T) = new scala.collection.immutable.::(x, this)中,然后执行Seq,最后进行通过类似(但更多参与/昂贵)的方式将Seq.toList的元素逐个添加到新列表中。

所以,第一种方式更有效,但我怀疑差异实际上是可以在任何类型的代码中检测到,您可以手动输入。

答案 1 :(得分:0)

使用List构造函数,每行编写一个list元素时将避免错误。例如,对于缺点,可能会编写以下错误:

val list =
  x1 ::
    x2 ::
    x3
    x4 ::
    Nil

它可以编译为list == List(x1, x2, x3),而不是所需的List(x1, x2, x3, x4),但是绝对不是假定的。

与List构造函数比较:

val list = List(
  x1,
  x2,
  x3,
  x4
)

如果您忘记在某些行的末尾使用逗号,则会发生编译错误。

在性能方面,第一种方法效率更高(请查看@dima的答案),但是您几乎永远看不到这一点。