【问题标题】:Scala: Returning a mutable buffer from a function that returns a SeqScala:从返回 Seq 的函数返回可变缓冲区
【发布时间】:2017-01-01 11:08:06
【问题描述】:

当我从 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

谢谢!

【问题讨论】:

    标签: java scala type-conversion mutable seq


    【解决方案1】:

    虽然 bar 被键入为 Seq[String],但它使用可变缓冲区 底层

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

    可能影响 Seq 操作的性能

    当您公开Seq[A] 时,您将公开基础集合所遵循的“合同”。在运行时,它将始终是一个具体的实现。即,当我们通过apply 创建Seq 时:

    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 的副本,他必须检查运行时类型并明确地转换为它,当你转换时,所有的赌注都关闭了。 p>

    【讨论】:

    • 有道理,感谢您的回答!我对 Scala 中的可变性有一种直觉反应,但实际上,不变性是许多底层 JVM 可变性之上的抽象——听起来即使在这种情况下,Seq 也提供了这种不变性抽象。
    • @Nathan 我理解你的直觉。当您使用 Scala 时,您希望一直努力实现不变性。但同样,在您的情况下,您必须努力绕过 Seq 抽象,并实际使用可变集合的可变性。
    • 出于好奇,如果我打电话给bar.asInstanceOf[scala.collection.mutable.Buffer[String]],它会使用 Seq 接口进行从 Seq 到可变缓冲区的通用转换,还是会尝试使用底层二进制表示进行原始转换?
    • asInstanceOf 只是一个演员表。
    猜你喜欢
    • 1970-01-01
    • 2017-05-21
    • 1970-01-01
    • 2012-11-23
    • 2010-12-17
    • 1970-01-01
    • 1970-01-01
    • 2021-06-04
    • 2014-07-21
    相关资源
    最近更新 更多