可变或不可变集?

时间:2013-02-09 11:16:13

标签: scala

请考虑以下事项:

scala> val myset = Set(1,2)
myset: scala.collection.immutable.Set[Int] = Set(1, 2)

scala> myset += 3
<console>:9: error: reassignment to val
              myset += 3
                    ^

scala> var myset = Set(1,2)
myset: scala.collection.immutable.Set[Int] = Set(1, 2)

scala> myset += 3

scala> myset
res47: scala.collection.immutable.Set[Int] = Set(1, 2, 3)

在一个案例中我可以添加“alex”而在另一个案例中我不能。 我知道val和var之间的区别。然而,在两种情况下让我困惑的是Scala告诉我Set是不可变的但它允许不同的行为。

我不想那样,因为在oncase myset是一个val而在一个中它是一个var。我想要一个更深层次的答案来解释为什么在两种情况下Scala都说myset是一个不可改变的集合,但却以不同的方式对待它们。因为它是反直觉的。

例如,使用可变集并将不可变集声明为var有什么不同吗? 为什么scala让你屈服于规则?如果说它是不可改变的,那会不会更好呢?

感谢。

3 个答案:

答案 0 :(得分:3)

首先让我们翻译+=电话

val myset = Set(1,2)
myset = myset + 3 //this is what the compiler does for myset += 3

这意味着我们实际上在+上调用Set方法,其scaladoc表示

  

使用其他元素创建 new 集,除非该元素已存在。

因此,代码尝试执行的操作是使用添加的元素创建 new Set并将其重新分配给不可变引用 {{1} }。

现在,如果我们将引用更改为可变引用(使用myset),那么您可以将其重新分配给新制作且不可变的 var

原始Set(1,2)仍然是不可变的,没有规则被破坏。让我们用一个案例来解释这个

Set(1,2,3)

正如您所看到的,var myset = Set(1,2) val holdIt = Some(myset) myset += 3 println(myset) // will print Set(1, 2, 3) println(holdIt)// will print Some(Set(1, 2)) 捕获的原始Set从未更改,我们只是重新指定了它对新创建的Option

的变量引用

答案 1 :(得分:2)

当您使用不可变集时,将创建一个新集并将其重新分配给var,这在使用val时是不可能的。但是一个可变的Set可以变异。虽然以下不是一个完美的保存演示,但它仍然显示使用不可变Set创建一个新对象,并且可变Set实例保持不变:

scala> var set1 = Set(1, 2)
set1: scala.collection.immutable.Set[Int] = Set(1, 2)

scala> System.identityHashCode(set1)
res0: Int = 2119337193

scala> set1 += 3

scala> System.identityHashCode(set1)
res2: Int = 1866831260

scala> var set2 = collection.mutable.Set(1, 2)
set2: scala.collection.mutable.Set[Int] = Set(2, 1)

scala> System.identityHashCode(set2)
res3: Int = 594308521

scala> set2 += 3
res4: scala.collection.mutable.Set[Int] = Set(2, 1, 3)

scala> System.identityHashCode(set2)
res5: Int = 594308521

答案 2 :(得分:2)

myset视为指针,将Set(1,2)视为对象

如果val myset指针只分配一次&amp;不能指向不同的对象(即指针是不可变的) 在var myset的情况下可以分配任意时间&amp;可以指向不同的对象(即指针是可变的

在这两种情况下,对象Set(1,2)都是不可变的。

当你这样做时

scala> val myset = Set(1,2)
myset: scala.collection.immutable.Set[Int] = Set(1, 2)

scala> myset += 3
<console>:9: error: reassignment to val
              myset += 3
                    ^

myset += 3实际上会为您添加一个新的Set并附加3 ..

由于myset指针是不可变的,因此您无法重新分配object方法返回的新+

其中

的情况
scala> var myset = Set(1,2)
myset: scala.collection.immutable.Set[Int] = Set(1, 2)

scala> myset += 3

由于myset指针是可变的,您可以重新分配object方法返回的新+