scala - Scala 中的嵌套默认映射

标签 scala dictionary default

我正在尝试在 Scala 中构造嵌套映射,其中外部映射和内部映射都使用“withDefaultValue”方法。例如,以下内容:

val m = HashMap.empty[Int, collection.mutable.Map[Int,Int]].withDefaultValue( HashMap.empty[Int,Int].withDefaultValue(3))
m(1)(2)
res: Int = 3
m(1)(2) = 5
m(1)(2) 
res: Int = 5
m(2)(3) = 6
m
res : scala.collection.mutable.Map[Int,scala.collection.mutable.Map[Int,Int]] = Map()

因此,当使用适当的键寻址时, map 会返回我输入的内容。但是, map 本身显示为空!在此示例中,甚至 m.size 也返回 0。谁能解释一下这是怎么回事?

最佳答案

简短回答

这绝对不是一个错误。

长答案

withDefaultValue 的行为是在 Map 中存储默认值(在您的情况下是可变映射),以便在键不存在时返回。这与未找到键时插入到 Map 中的值不同。

让我们仔细看看发生了什么。如果我们将默认映射作为单独的变量取出,以便我们可以随意检查,会更容易理解;我们称之为默认

import collection.mutable.HashMap
val default = HashMap.empty[Int,Int].withDefaultValue(3)

所以 default 是一个可变映射(有自己的默认值)。现在我们可以创建 m 并指定 default 作为默认值。

import collection.mutable.{Map => MMap}
val m = HashMap.empty[Int, MMap[Int,Int]].withDefaultValue(default)

现在,每当使用丢失的 key 访问 m 时,它将返回 default。请注意,这与您的行为完全相同,因为 withDefaultValue 定义为:

def withDefaultValue (d: B): Map[A, B]

请注意,它是 d: B 而不是 d: => B,因此每次访问默认值时不会创建新 map ;它将返回完全相同的对象,我们称之为default

让我们看看会发生什么:

m(1) // Map()

由于键 1 不在 m 中,因此返回默认值 default。此时的default是一个空Map。

m(1)(2) = 5

由于 m(1) 返回 default,因此此操作将 5 作为键 2 的值存储在 default 中。没有向 Map m 写入任何内容,因为 m(1) 解析为 default,它完全是一个单独的 Map。我们可以通过查看default来检查这一点:

default // Map(2 -> 5)

但正如我们所说,m 保持不变

m // Map()
<小时/>

现在,如何实现您真正想要的?您希望使用 getOrElseUpdate,而不是使用 withDefaultValue:

def getOrElseUpdate (key: A, op: ⇒ B): B

注意我们如何看到op: => B吗?这意味着每次需要时都会重新评估参数op。这允许我们在其中放置一个新的 Map,并使其成为每个无效键的单独的新 Map。我们来看看:

val m2 = HashMap.empty[Int, MMap[Int,Int]]

此处不需要默认值。

m2.getOrElseUpdate(1, HashMap.empty[Int,Int].withDefaultValue(3)) // Map()

键 1 不存在,因此我们插入一个新的 HashMap,并返回该新值。我们可以检查它是否按照我们的预期插入。请注意,1 映射到新添加的空映射,并且由于上面解释的行为,它们 3 没有添加到任何地方。

m2 // Map(1 -> Map())

同样,我们可以按预期更新 map :

m2.getOrElseUpdate(1, HashMap.empty[Int,Int].withDefaultValue(1))(2) = 6

并检查它是否已添加:

m2 // Map(1 -> Map(2 -> 6))

关于scala - Scala 中的嵌套默认映射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8904823/

相关文章:

go - 是否需要为变量分配默认值?

scala - SBT 准备 WAR 文件,重复条目 : META-INF/MANIFEST. MF

scala - 从案例类中过滤出一个字段

scala - Scala for 推导式中 val 的作用域规则是什么

python字典将键的值放入一个列表中,其中键在另一个列表中

python 获取列表中的字典值

如果未找到,则正则表达式默认值

scala - 使用空参数从Scala调用Java API

python - 使用基于条件的字典替换 python 数据框中的列值

Android默认旋转箭头资源