为什么 'scala.collection.mutable.Map's 的 'withDefaultValue's 不能正确保留默认值?

Why do `scala.collection.mutable.Map`s `withDefaultValue`s not properly retain default values?

提问人:Scoobie 提问时间:8/23/2022 更新时间:8/23/2022 访问量:45

问:

这是怎么回事?

Welcome to Scala 2.13.5 (OpenJDK 64-Bit Server VM, Java 1.8.0_312).

...

> import scala.collection.mutable.{Map => MMap, ListBuffer => MList}
import scala.collection.mutable.{Map=>MMap, ListBuffer=>MList}

> val m = MMap[String, MList[String]]().withDefaultValue(MList[String]())
val m: scala.collection.mutable.Map[String,scala.collection.mutable.ListBuffer[String]] = Map()

> m("a")
val res0: scala.collection.mutable.ListBuffer[String] = ListBuffer()

> m("a").addOne("b")
val res1: scala.collection.mutable.ListBuffer[String] = ListBuffer(b)

> m
val res2: scala.collection.mutable.Map[String,scala.collection.mutable.ListBuffer[String]] = Map()

> m.keys
val res3: Iterable[String] = Set()

> m("a")
val res4: scala.collection.mutable.ListBuffer[String] = ListBuffer(b)

为了便于阅读,上面的一些文字已被删除

斯卡拉 收集 可变

评论

1赞 Luis Miguel Mejía Suárez 8/23/2022
可变性和一般都是非常糟糕的想法,我建议您寻找不同的解决方案来解决导致您遇到这个问题的任何元问题。withDefaultValue

答:

2赞 Alin Gabriel Arhip 8/23/2022 #1

由于默认值是可变的,因此您只是更改了默认值。但是你从来没有在里面插入任何东西,这就是为什么你看不到里面的任何东西。Map

m("a")是语法糖,由于该键没有值,但设置了默认值,因此它会导致您之前设置的默认值。m.apply("a")

如果您要查看 withDefaultValue 文档,则会看到以下内容:

具有给定默认值的相同映射。注意:默认值仅为 用于 .其他方法如 、 、 、 等。 不受 的影响。调用 transformer 方法 (例如)不会保留默认值。applygetcontainsiteratorkeyswithDefaultValuemap

由于它是可变的,因此在使用默认值的方法时,您将直接更改默认值的内容。ListBufferaddOne

所以现在每个没有值的键都会导致:MapListBuffer(b)

scala> m("a")
val res1: scala.collection.mutable.ListBuffer[String] = ListBuffer(b)

scala> m("c")
val res2: scala.collection.mutable.ListBuffer[String] = ListBuffer(b)

scala> m("whatever")
val res3: scala.collection.mutable.ListBuffer[String] = ListBuffer(b)

如果希望 immutable 保持不变,则应使用 immutable 作为默认值。List