为什么Seq.newBuilder返回ListBuffer?

Ber*_*ium 3 scala scala-collections

看着

val sb = Seq.newBuilder[Int]
println(sb.getClass.getName)
sb += 1
sb += 2
val s = sb.result()
println(s.getClass.getName)
Run Code Online (Sandbox Code Playgroud)

输出是

scala.collection.mutable.ListBuffer
scala.collection.immutable.$ colon $ colon

使用Scala 2.10.1.

我希望Seq.newBuilder能回来一个VectorBuilder例子.这是由返回CanBuildFrom,如果结果是显式类型的Seq:

def build[T, C <: Iterable[T]](x: T, y: T)
                              (implicit cbf: CanBuildFrom[Nothing, T, C]): C = {
  val b = cbf()
  println(b.getClass.getName)
  b += x
  b += y
  b.result()
}

val s: Seq[Int] = build(1, 2)
println(s.getClass.getName) // scala.collection.immutable.Vector
Run Code Online (Sandbox Code Playgroud)

在这种情况下,构建器是a VectorBuilder,结果的类是a Vector.

所以我明确地希望构建一个Seq,但结果是List需要更多RAM,根据Scala集合内存占用特征.

那么为什么Seq.newBuilder返回一个ListBuffer最终会给出一个List

Fyn*_*ynn 6

Scala集合API是非常复杂的,它的层次是丰富的层次.每个级别代表某种新的抽象.该Seq特征分为两个不同的子特征,它们为性能提供不同的保证(参考):

  1. An IndexedSeq提供元素的快速随机访问和快速长度操作.其中一个代表IndexedSeq就是Vector.

  2. A LinearSeq通过磁头仅提供对第一个元素的快速访问,但也具有快速尾部操作.其中一个代表LinearSeq就是List.

由于a的当前默认实现Seq是a List,Seq.newBuilder将返回a ListBuffer.但是,如果你想使用a,Vector你可以使用Vector.newBuilder[T]IndexedSeq.newBuilder[T]:

scala> scala.collection.immutable.IndexedSeq.newBuilder[Int]
res0: scala.collection.mutable.Builder[Int,scala.collection.immutable.IndexedSeq[Int]] = scala.collection.immutable.VectorBuilder@1fb10a9f

scala> scala.collection.immutable.Vector.newBuilder[Int]
res1: scala.collection.mutable.Builder[Int,scala.collection.immutable.Vector[Int]] = scala.collection.immutable.VectorBuilder@3efe9969
Run Code Online (Sandbox Code Playgroud)