我正在尝试创建这样的对象地图:
case class Worker(var name:String, var tasks:List[Int]=List())
val map = Map[Int, Worker]().withDefaultValue(Worker(""))
因此,每当有新的请求id(地图中的键)进来时,我就可以为该id创建一个新的worker对象。我不知道会有多少请求id或id的范围。但是这段代码给出了一个非常奇怪的结果。
scala> map.size
res34: Int = 0
scala> map(1).name = "first worker"
map(1).name: String = first worker
scala> map.size
res35: Int = 0
scala> map(3).name = "request #3"
map(3).name: String = request #3
scala> map.size
res36: Int = 0
scala> map(1).name
res37: String = request #3
这不是我预期的结果。地图大小始终为0.没有创建新的Worker对象。我尝试使用可变和不可变的地图,案例类和常规类与新工作者,并尝试{ override def default(key:Int)=Worker("") }
。什么都没有按预期工作。有人可以帮我理解withDefaultValue的行为或覆盖def默认值吗?或scala方式这样做?我知道我可以用java方式实现这个if map.containsKey(xx) map.get(xx).name = "abc" else map.put(xx, new Worker)
。但这很乏味。
答案 0 :(得分:1)
访问Map
的默认值不会将该值作为新值添加到Map
本身。您只是每次都改变相同的默认值(相同的参考)。对于标准Map
实现来说,改变自己是非常意外的。
要实现您想要的功能,您实际上可能希望覆盖apply
方法,以便在找不到新元素时向Map
添加新元素。
import scala.collection.mutable.HashMap
case class Worker(var name: String, var tasks: List[Int] = Nil)
class RequestMap extends HashMap[Int, Worker] { self =>
override def apply(a: Int): Worker = {
super.get(a) match { // Find the element through the parent implementation
case Some(value) => value // If it exists, return it
case None => {
val w = Worker("") // Otherwise make a new one
self += a -> w // Add it to the Map with the desired key
w // And return it
}
}
}
}
这可以满足您的需求,但它只是您可以采取的方向示例。它不是线程安全的,并且需要某种锁定机制来实现它。
scala> val map = new RequestMap
map: RequestMap = Map()
scala> map(1)
res3: Worker = Worker(,List())
scala> map(2)
res4: Worker = Worker(,List())
scala> map.size
res5: Int = 2