在收集的 scala 文档中,我发现以下语句为:
"根集合 (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
采用不可变集合。这需要两件事:- 对于
bar
的调用者:将集合传递给bar
永远不会修改它,我们保证bar
时集合是完整的> 返回。 - 对于
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/