How does Scala's mutable Map update [map(key)

2020-02-09 07:13发布

问题:

I'm working through Cay Horstmann's Scala for the Impatient book where I came across this way of updating a mutable map.

scala> val scores = scala.collection.mutable.Map("Alice" -> 10, "Bob" -> 3, "Cindy" -> 8)
scores: scala.collection.mutable.Map[String,Int] = Map(Bob -> 3, Alice -> 10, Cindy -> 8)

scala> scores("Alice") // retrieve the value of type Int
res2: Int = 10

scala> scores("Alice") = 5 // Update the Alice value to 5

scala> scores("Alice")
res4: Int = 5

It looks like scores("Alice") hits apply in MapLike.scala. But this only returns the value, not something that can be updated.

Out of curiosity I tried the same syntax on an immutable map and was presented with the following error,

scala> val immutableScores = Map("Alice" -> 10, "Bob" -> 3, "Cindy" -> 8)
immutableScores: scala.collection.immutable.Map[String,Int] = Map(Alice -> 10, Bob -> 3, Cindy -> 8)

scala> immutableScores("Alice") = 5
<console>:9: error: value update is not a member of scala.collection.immutable.Map[String,Int]
              immutableScores("Alice") = 5
          ^

Based on that, I'm assuming that scores("Alice") = 5 is transformed into scores update ("Alice", 5) but I have no idea how it works, or how it is even possible.

How does it work?

回答1:

This is an example of the apply, update syntax.

When you call map("Something") this calls map.apply("Something") which in turn calls get.

When you call map("Something") = "SomethingElse" this calls map.update("Something", "SomethingElse") which in turn calls put.

Take a look at this for a fuller explanation.



回答2:

Can you try this: => to update list of Map

import java.util.concurrent.ConcurrentHashMap
import scala.collection.JavaConverters._
import scala.collection.concurrent

val map: concurrent.Map[String, List[String]] = new ConcurrentHashMap[String, List[String]].asScala

def updateMap(key: String, map: concurrent.Map[String, List[String]], value: String): Unit = {
map.get(key) match {
case Some(list: List[String]) => {
val new_list = value :: list
map.put(key, new_list)
}
case None => map += (key -> List(value))
}
}


回答3:

The problem is you're trying to update immutable map. I had the same error message when my map was declared as

var m = new java.util.HashMap[String, Int]

But when i replaced the definition by

var m = new scala.collection.mutable.HashMap[String, Int]

the m.update worked.