所以我有点困惑。我在Scala中有一段代码(确切的代码并不是那么重要)。我把所有的方法写成了Seq [T]。这些方法主要是尾递归,并使用Seq [T]作为累加器,它最初像Seq()一样被馈送。有趣的是,当我将所有签名与具体的List()实现交换时,我观察到性能提高了三倍。
是不是Seq的默认实现实际上是一个不可变的List?那么如果是这样的话,究竟发生了什么?
答案 0 :(得分:1)
致电Seq(1,2,3)
并致电List(1,2,3)
都会产生1 :: 2 :: 3 :: Nil
。 Seq.apply
方法只是一个非常通用的方法,如下所示:
def apply[A](elems: A*): CC[A] = {
if (elems.isEmpty) empty[A]
else {
val b = newBuilder[A]
b ++= elems
b.result()
}
}
newBuilder
在这里很重要。 That method代表scala.collection.immutable.Seq.newBuilder
:
def newBuilder[A]: Builder[A, Seq[A]] = new mutable.ListBuffer
因此Builder
的{{1}}是Seq
。通过将元素附加到空mutable.ListBuffer
然后在其上调用result
来构建Seq
,其实现如下:
ListBuffer
def result: List[A] = toList
/** Converts this buffer to a list. Takes constant time. The buffer is
* copied lazily, the first time it is mutated.
*/
override def toList: List[A] = {
exported = !isEmpty
start
}
也有List
ListBuffer
。它经历了一个略有不同但相似的建筑过程。无论如何,这并不会产生很大的不同,因为我认为你的大多数算法都会在Builder
之前添加内容,而不是一直调用Seq
。即使你这样做也不应该有太大的不同。
在没有看到具有该行为的代码的情况下,真的无法说出导致您所看到的行为的原因。