scala - scala中根集合和不可变集合之间的区别

标签 scala collections

在收集的 scala 文档中,我发现以下语句为:

docs here

"根集合 (scala.collection) 和不可变集合 (scala.collection.immutable) 的区别在于,不可变集合的客户端具有保证没有人可以改变集合,而根集合的客户端只 promise 不会自己更改集合。即使此类集合的静态类型不提供修改集合的操作,运行时仍有可能type 是一个可变集合,可以被其他客户端更改。 "

但我没听懂这句话,“而根集合的客户只 promise 不会自己更改集合”,这是在说什么?

最佳答案

让我们考虑三种可能性:

def foo(it: scala.collection.mutable.Iterable[Int]) = ???    
def bar(it: scala.collection.immutable.Iterable[Int]) = ???
def baz(it: scala.collection.Iterable[Int]) = ???
  • foo 采用可变集合,因此有权对其进行修改。 如果您调用 foo,您必须期望作为调用者该集合被 foo 修改(它可能不会,但您无法判断)。作为实现者,您还必须考虑在 foo 执行时修改集合的可能性。

  • bar 采用不可变集合。这需要两件事:

    1. 对于bar的调用者:将集合传递给bar永远不会修改它,我们保证bar时集合是完整的> 返回。
    2. 对于 bar 本身:在实现 bar 的主体时可以安全地认为集合不会在 bar 时更改正在执行。
  • baz 采用“根”集合。与不可变集合不同,只有第 (1) 点成立。换句话说,只有 baz 的调用者在这里有任何保证:将集合传递给 baz 永远不会修改它,并且我们保证在 时集合是完整的>baz 返回。 相反,在实现 baz 时,我们不能保证集合在 baz 执行时不会改变,因为虽然 baz 本身不能修改由于“根”集合上缺少变异方法,集合仍然有可能实际上是可变的,并且将被另一个线程修改。

考虑一下:

val buf = collection.mutable.Buffer[Int](1,2,3)
def baz(it: scala.collection.Iterable[Int]) = {
  println(it)
  Thread.sleep(2000)
  println(it)
}
new Thread {
  override def run() {
    Thread.sleep(1000)
    buf += 4
  }
}.start()
baz(buf)

以及由此产生的痕迹:

ArrayBuffer(1, 2, 3)
ArrayBuffer(1, 2, 3, 4)

在上面的代码片段中,我们创建了一个可变集合并将其传递给 baz,它需要一个“根”集合。然后我们在 baz 执行时修改集合,证明 baz 不能依赖 it 在执行时不改变。

关于scala - scala中根集合和不可变集合之间的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36399554/

相关文章:

scala - 主方法中的Scala App val初始化

java - groupingBy 带 boolean 值,但添加自定义字符串作为键

scala - 将毫秒中的当前时间转换为Scala中的日期时间格式

scala - 对象中奇怪的类名的含义

scala - 在样式中使用Scala隐式编码

java - 克隆和减法集 - 这行得通吗?

java合并两个链表

java - 使用流 API 将 arraylist 添加到 arraylist

java - Hashmap jdk1.7无锁get()和同步put()的线程安全

scala - 二进制序列化 - 在 Scala 2.10 上替换 Marshal