提问人:worldterminator 提问时间:3/7/2022 更新时间:3/7/2022 访问量:187
具有可变默认值的 Scala 映射始终指向同一对象
Scala Map with mutable default value always point to the same object
问:
Scala 版本:3.1
我想创建一个 String -> Int 映射,每个键都可以指向许多 Int。
因此,我选择默认可变的映射。Buffer[Int]
但似乎所有的键总是指向同一个Buffer[Int]
请注意,在第一个中也很奇怪,在此之后它不打印任何内容,但默认值发生了变化,因此它在下一个中打印了两个 1。 m("a") += 1
+=
println
另外,我如何解决被 .如果键不存在,我希望地图插入一个新的,然后调用.mutable.Map
+=
Buffer
+=
Buffer
+=
buffer
import scala.collection.mutable
val m: mutable.Map[String, mutable.Buffer[Int]] =
mutable.HashMap.empty.withDefaultValue(mutable.Buffer.empty)
m("a") += 1
println(m) // Map()
m("a") = m("a") += 1
println(m) // Map(a -> ArrayBuffer(1, 1))
m("b") = m("b") += 2 // Map(a -> ArrayBuffer(1, 1, 2), b -> ArrayBuffer(1, 1, 2)) , not expecting this, key is correct but
println(m) // Map(a -> ArrayBuffer(1, 1, 2), b -> ArrayBuffer(1, 1, 2))
m("a") = m("a") += 2
println(m) // Map(a -> ArrayBuffer(1, 1, 2, 2), b -> ArrayBuffer(1, 1, 2, 2)) ,
// this is not as I expected. The keys are correct, however their values are all the same ArrayBuffer
答:
4赞
Koterpillar
3/7/2022
#1
TL;DR:在这里没用。withDefaultValue
请注意,withDefaultValue
的签名为:
def withDefaultValue(d: V): Map[K, V]
该参数是按值而不是按名称 () 获取的,因此仅计算一次。因此,原始映射中不存在的任何键都将返回您创建的相同空缓冲区。d
=> V
你得到的(和)是一个新的类似地图的对象,而不是原始地图。只有赋值结果 () 才会改变它。withDefaultValue
withDefault
m("a") = ...
注意:默认值仅用于应用。其他方法(如 get、contains、iterator、keys 等)不受 withDefaultValue 的影响。
请看这个例子:
val m = new HashMap[Integer, Buffer[String]]()
val mm = m.withDefault(_ => Buffer.empty)
mm(1).append("4")
mm(1) // ArrayBuffer()
您可能想要的是带有签名的 getOrElseUpdate
(如果您愿意,可以定义一个辅助函数)
getOrElseUpdate(key: K, defaultValue: => V): V
注意这次如何按名称调用,每次调用都会创建一个新的缓冲区:defaultValue
val m: mutable.Map[String, mutable.Buffer[Int]] =
mutable.HashMap.empty
def mm(key: String): mutable.Buffer[Int] = m.getOrElseUpdate(key, mutable.Buffer.empty)
mm("a") += 1
mm("b") += 2
// now buffers at `a` and `b` are distinct
评论