Scala不可变集是可变的吗?

Scala不可变集是可变的吗?,scala,set,immutable-collections,Scala,Set,Immutable Collections,文件说: 包scala.collection.immutable中的集合保证对每个人都是不可变的这样的集合在创建后将永远不会更改 但我没有从中得到我期望的行为: scala> var test3 = scala.collection.immutable.Set[String]("one", "two") test3: scala.collection.immutable.Set[String] = Set(one, two) scala> test3 += "three" sca

文件说:

包scala.collection.immutable中的集合保证对每个人都是不可变的这样的集合在创建后将永远不会更改

但我没有从中得到我期望的行为:

scala> var test3 = scala.collection.immutable.Set[String]("one", "two")
test3: scala.collection.immutable.Set[String] = Set(one, two)

scala> test3 += "three"

scala> println(test3)
Set(one, two, three)

我错过了什么

在处理集合时,有两件事需要避免(如果可能的话)。正如您所知,不可变集合比可变集合更受欢迎。然而,将不可变集合存储在可变变量中只会“延迟”问题。您将易变性及其带来的所有问题从集合本身转移到保存集合的变量。不管怎样,你都有一个状态


理想的解决办法是避免两者兼而有之。也就是说,同时使用不可变集合和不可变字段(VAL)。例如,一个函数可以生成一个不可变的集合,而其他函数可以使用它,而无需将集合本身保留在某个位置或对其进行修改。

a
var
可以重新赋值(它是一个变量,因此可以变化)。然后,您将不再引用上一个对象

无法重新分配
val
(它是一个值,因此不能改变),但您可以调用该对象上的方法,例如,如果该值是一个
可变的集

当我说vary时,我的基本意思是,引用不能改变。我知道这有点让人困惑

换句话说,
val
s和
var
s都可以指向内部状态可以改变的对象。就像一张可变的地图

我鼓励您自己编写一个验证此表的代码示例:


Set
是不可变的,但是您正在重新分配给
var
,并且
var
是可变的。
+=
是语法糖,在本例中为
test3=test3+“三”
。尝试将test3设置为
val
,您会遇到一条消息,说test3不能被重新分配。@EndeNeu-那么为什么首先要设置不可变集和可变集呢?为什么不根据需要使用var或val声明它们呢?@snappymcsnap因为可变集和不可变集的实现有很大的不同!请记住,对象易变性和引用易变性之间是有区别的。如果对象的属性可以更改,则该对象是可变的
test3
是对不可变对象的可变引用,但是
test3
可以更改为指向不同的对象。好的,这是一个很好的经验法则,谢谢。所以基本上使用var会创建一个临时变量……当你第一次分配它时,它指向内存中的一个特定引用(不可变),一旦你添加到它,它会创建一个全新的不可变集(带有新项),所以变量指向一个全新的引用。我知道那会给你带来什么麻烦。好的,所以我使用val,就像我在Java中使用'final'关键字一样,以确保我的不可变始终是不可变的。使用var意味着变量可以更改其值,这意味着在某个点上它持有对某个不可变集合的引用,但随后该引用可以指向完全不同的不可变集合。只有一件事——我不一定把var称为“临时的”。我的意思是,它是,但和Java中的任何普通变量一样多。更正确的说法是var是可变的(请原谅这个愚蠢的术语)。它的值可以被重新分配,而VAL是不可能的(您在Java中使用了一个与final的正确并行)。这是一个方便的图表,可以一目了然地看到发生了什么。谢谢
    | MutableSet                    | ImmutableSet
--------------------------------------------------
var | Reassign. Insert element      | Reassign
val | Insert                        | None of these