Scala 带var的不可变映射还是带val的可变映射?

Scala 带var的不可变映射还是带val的可变映射?,scala,concurrency,immutability,scala-collections,mutable,Scala,Concurrency,Immutability,Scala Collections,Mutable,以下两个代码段中,哪一个更有效且行为正确 // snippet 1 var map = Map[String, Int]() // immutable map with var map.synchronized(map += "hello" -> 1) map.synchronized(map -= "hello") // snippet 2 val mmap = scala.collection.mutable.Map[String, Int]() mmap.synchronize

以下两个代码段中,哪一个更有效且行为正确

// snippet 1
var map = Map[String, Int]()   // immutable map with var
map.synchronized(map += "hello" -> 1)
map.synchronized(map -= "hello")

// snippet 2
val mmap = scala.collection.mutable.Map[String, Int]()
mmap.synchronized(mmap += "hello" -> 1)
mmap.synchronized(mmap -= "hello")

编辑:我正在研究并发访问地图的情况,在这种情况下,多个不同的参与者共享同一个地图并希望修改它。另外,链接的问题涉及
var
val
的一般情况,而我需要了解
Map
集合类型。

这取决于可变对象和不可变对象都有其pro和con

不可变对象使并发编程更容易、更安全,并且您可以轻松地对其进行推理。JVM并发性周围发生的大多数运行时错误都是由于共享的可变状态造成的

如果对象变大,仅为了保持不变状态而复制对象是没有意义的。在设计算法时,你必须明智地思考


soote:你为什么不能把这张地图放在一个演员里面,让其他演员使用消息来修改/阅读它


Jus12:@soote仔细想想,你是对的!我将使用适当的参与者模型来实现它

soote确实是对的:因为您显然在使用一个actor系统,所以地图应该驻留在一个actor中。一般来说,当在参与者内部表示可变状态时,应该使用带有
var
的不可变数据结构,而不是带有
val
的可变数据结构。这样做的原因是为了防止该状态泄漏到参与者的边界之外。以下是使用Akka的具体示例:

case object GetState
case class Add(key: String, value: Int)
case class Remove(key: String)

class MyActor extends Actor {
  val state = mutable.Map[String, Int]()

  def receive = {
    case GetState =>
      sender ! state
    case Add(k, v) =>
      state += (k -> v)
    case Remove(k) =>
      state -= k
  }
}
当上述参与者收到
GetState
消息时,它将其内部映射发送给发送者。由于映射是可变的,发送方现在可以从参与者外部修改映射,从而允许破坏参与者的状态。要防止此泄漏,请将易变性限制到参与者本身:

class MyActor extends Actor {
  var state = Map[String, Int]() // immutable map

  def receive = {
    case GetState =>
      sender ! state
    case Add(k, v) =>
      state = state + (k -> v)
    case Remove(k) =>
      state = state - k
  }
}

现在,
MyActor
可以安全地将其状态发送给其他参与者,因为它的状态是一个不可变的映射。

上述问题的可能重复没有明确地处理并发性。是否有原因不能将此映射放置在参与者内,并让其他参与者使用消息修改/读取它?我可以尝试,但需要重复,我需要参与者之间的共享状态,这对于实现消息来说太过分了passing@soote再想想,你是对的!我将使用合适的参与者模型来实现它。那么另一个答案中的注释呢
如果对象变大,仅为了保持不变状态而复制对象是没有意义的。
映射确实很大,大约有10k个条目。