Scala:从返回Seq

时间:2016-08-25 06:28:08

标签: java scala type-conversion mutable 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包含的值视为可变或不可变?

请原谅这个问题是多么开放,但我不觉得我很清楚发生了什么,我想改变这个问题。例如,在从scalaMutableBuffer返回之前,是否会优先转换toList foo

谢谢!

1 个答案:

答案 0 :(得分:4)

  

当bar被键入为Seq [String]时,它使用可变缓冲区   基础水平

你是对的,bar的运行时价值是mutable.ArrayBuffer[String](因为Buffer是一个特质本身),而Seq[+A]是一个特质,你作为一个来电者只能看到"顺序" ArrayBuffer的部分内容,尽管您始终可以通过buffer.asInstanceOf[mutable.ArrayBuffer[String]]将其转换为缓冲区,然后查看实际的"内部"缓冲区。

  

可能影响Seq操作的性能

当一个人曝光Seq[A]时,你就会暴露"合同"底层集合坚持。在运行时,它将始终是一个具体的实现。即,当我们通过Seq

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

具体实现实际上是List[Int]

  

最好将值栏视为可变或   不可变?

底层实现是可变的,但是通过不可变合约公开。这意味着当您通过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

抽象保护我们不要让用户调用我们不希望他们在运行时类型上执行的操作。

  

例如,是否会出现更优先的情况   让我从foo返回之前将scalaMutableBuffer转换为List

我认为这主要是基于意见的。如果你感觉不到Seq特征,你总是可以使具体类型成为不可变的。但请记住,为了让某人改变Seq的副本,他必须检查运行时类型并明确地投射到它,并且当你投下所有投注时都会关闭。