Scala集不变性

Scala集不变性,scala,immutability,Scala,Immutability,我想知道,允许将var与不可变集一起使用有什么好处?在这种情况下,我没有失去不变性吗 允许使用var有什么好处 使用不可更改的集合s 我认为这主要会引起混乱。使用var可以覆盖变量,但是Set本身不会改变,它会用附加值“C”分配一个新的集合。但是,由于您使用的是var,因此现在不再引用以前的集合,除非您引用的是堆栈中较高的其他位置: scala> var immSet = Set("A", "B") immSet: scala.collection.immutable.Set[String

我想知道,允许将
var
与不可变集一起使用有什么好处?在这种情况下,我没有失去不变性吗

允许使用
var
有什么好处 使用不可更改的
集合
s

我认为这主要会引起混乱。使用
var
可以覆盖变量,但是
Set
本身不会改变,它会用附加值“C”分配一个新的集合。但是,由于您使用的是
var
,因此现在不再引用以前的
集合
,除非您引用的是堆栈中较高的其他位置:

scala> var immSet = Set("A", "B")
immSet: scala.collection.immutable.Set[String] = Set(A, B)

scala> immSet += "C"

scala> println(immSet)
Set(A, B, C)
因为
secondSet
仍然指向由
firstSet
创建的
Set
,所以我们看不到反映的值更新。我认为,将此设置为不可变可以清楚地看出,底层的
集合
是不可变的,并且指向它的变量也是不可变的。当您使用
val
时,如果您尝试重新分配,编译器将大叫,迫使您意识到新集合已初始化


关于不变性,我们需要将其分为两部分。有
集合
的不变性,也有指向该
集合
的变量的不变性,这是两件不同的事情。如果您想了解定义为
var
的不可变集合和定义为
val
的可变集合之间的基本区别,请阅读@YuvalItzchakov的答案。我将集中讨论这两种方法的实际方面

首先,这两种方法都意味着可变性。如果你想保持“纯粹的功能性”,你应该避免它们中的任何一个

现在,如果您想要可变集合,最好的方法是什么?简短的回答,视情况而定

  • 表演。可变集合通常比不可变集合快。这意味着,如果可变变量以某种方式被包含(例如,不转义私有方法),则最好使用
    val c=MutableCollection()
    。集合API中的大多数Scala方法在内部使用可变集合

  • 线程安全。不可变集合的值始终是线程安全的。您可以将其发送到另一个线程,而不考虑可见性和并发更改

    scala> var firstSet = Set("A", "B")
    firstSet: scala.collection.immutable.Set[String] = Set(A, B)
    
    scala> var secondSet = firstSet
    secondSet: scala.collection.immutable.Set[String] = Set(A, B)
    
    scala> firstSet += "C"
    
    scala> firstSet
    res6: scala.collection.immutable.Set[String] = Set(A, B, C)
    
    scala> secondSet
    res7: scala.collection.immutable.Set[String] = Set(A, B)
    
    另一方面,如果您想修改来自多个线程的集合,最好使用Java的并发集合API

  • 代码清晰。假设您有一个函数,它将集合作为参数,然后以某种方式对其进行修改。若集合是可变的,那个么在函数返回后,作为参数传递的集合将保持修改状态

    var a = ImmutableCol()
    otherThreadProcessor.process(a)
    a += 1 // otherThread will still have previous value
    

  • 谢谢你的解释!!!我想知道我的集合是否是不可变的,我希望我的变量也是不可变的,我想知道在现实世界中的哪个场景中,我们希望设置为不可变的,但变量不是..@JackDaniel's,我理解。我只是想指出,在现实生活中这样做可能会让任何阅读你的代码的人感到困惑。@JackDaniel这样做的一个原因是,你可以将这个集合传递给任何函数,并确保它不会改变(如果这个函数将这个集合存储在某个地方,你也不必担心你会改变
    var
    ).关于第一点,我认为OP指的是使用可变变量的不可变集合的特定场景,而不是一般使用可变集合。
    def recImmutable(a:Set[Int]): Unit = {
      var b = a
      b += 4
    }
    
    val a = Set(2,3)
    recImmutable(a)
    println(a)
    // prints Set(2, 3)
    
    def recMutable(a:mutable.Set[Int]): Unit = {
      var b = a
      b += 4
    }
    
    val b = mutable.Set(2,3)
    recMutable(b)
    println(b)
    // prints Set(2, 3, 4)