Scala:从 returns 一个 Seq 的函数返回一个可变缓冲区

Scala: Returning a mutable buffer from a function that returns a Seq

当我从 Java List 转换为通用 Scala Seq:

时,我想更好地理解这段代码中实际发生的事情
import scala.collection.JavaConverters._

def foo(javaList: java.util.List[String]): Seq[String] = {
  val scalaMutableBuffer: mutable.Buffer[String] = javaList.asScala
  scalaMutableBuffer
}

... 

val bar = foo(someJavaList)

我的理解是否正确,虽然 bar 被键入为 Seq[String],但它在底层使用可变缓冲区,可能会影响 Seq 操作的性能? Seq 是通过 Seq 特征的约束简单地引用缓冲区,还是存在实际的底层转换?最好将 bar 包含的值视为可变的还是不可变的?

请原谅这个问题的开放性,但我觉得我不太清楚发生了什么,我想改变它。例如,在从 foo 返回之前转换 scalaMutableBuffer toList 是否更可取?

谢谢!

while bar is typed as a Seq[String], it's using a mutable buffer on an underlying level

你是对的,bar的运行时间值是一个mutable.ArrayBuffer[String](因为Buffer本身就是一个特征),并且Seq[+A] 是一个特征,作为调用者,您只能看到 ArrayBuffer 的 "sequency" 部分,尽管您始终可以通过 buffer.asInstanceOf[mutable.ArrayBuffer[String]] 将其转换为缓冲区,然后看到实际的 "internals" 缓冲区。

potentially affecting the performance of Seq operations

当公开 Seq[A] 时,您公开的是基础集合所遵循的 "contract"。在运行-时间,它永远是一个具体的实现。即,当我们通过 apply:

创建一个 Seq
scala> Seq(1,2,3)
res0: Seq[Int] = List(1, 2, 3)

具体实现其实就是一个List[Int].

Would it be best to think of the value bar contains as mutable or immutable?

底层实现是可变的,但通过不可变合约公开。这意味着当您通过 Seq 特征的抽象对缓冲区进行操作时,作为调用者您没有可用的可变操作。

例如,当我们这样做时:

scala> val bufferAsSeq: Seq[Int] = scala.collection.mutable.Buffer(1,2,3)
bufferAsSeq: Seq[Int] = ArrayBuffer(1, 2, 3)

scala> bufferAsSeq += 4
<console>:12: error: value += is not a member of Seq[Int]
       bufferAsSeq += 4

抽象防止我们让用户调用我们不希望他们在 运行-time 类型上执行的操作。

For example, would there be any cases in which it would be preferable for me to convert scalaMutableBuffer toList before returning from foo

我认为这主要是基于意见。如果你感觉不到 Seq 特性,你总是可以让具体类型不可变。但是请记住,为了让某人改变 Seq 的副本,他必须检查 运行-time 类型并 显式转换为它 ,并且当你投了所有赌注。