加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

Scala中的嵌套默认地图

发布时间:2020-12-16 09:01:23 所属栏目:安全 来源:网络整理
导读:我正在 Scala中构建嵌套的地图,其中外层和内部地图都使用“withDefaultValue”方法.例如,以下内容: val m = HashMap.empty[Int,collection.mutable.Map[Int,Int]].withDefaultValue( HashMap.empty[Int,Int].withDefaultValue(3))m(1)(2)res: Int = 3m(1)(2
我正在 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()

所以地图,当由适当的钥匙处理时,给我回到我所投入的东西.但是,地图本身就是空的!即使m.size在此示例中返回0.任何人都可以解释这里发生了什么吗?

解决方法

简短答案

这绝对不是一个bug.

长答案

withDefaultValue的行为是在Map中存储一个默认值(在你的情况下是一个可变地图),以便在它们的键不存在的情况下返回.这与在没有找到密钥时插入到地图中的值不同.

我们来看看发生了什么事情.如果我们将默认地图作为单独的变量拖出来,我们可以随意查看,这将会更容易理解.我们称之为默认

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

所以默认是一个可变地图(有自己的默认值).现在我们可以创建m并给出默认值作为默认值.

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

现在每当使用缺少的密钥访问m时,它将返回默认值.请注意,这与您的行为完全相同,因为将DefaultValue定义为:

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

请注意,它是d:B而不是d:=> B,所以每次默认访问时都不会创建一个新的地图;它将返回相同的精确对象,我们称之为默认对象.

所以让我们看看会发生什么:

m(1) // Map()

由于键1不在m中,默认值为默认值.这时默认是一个空的地图.

m(1)(2) = 5

由于m(1)返回默认值,此操作默认存储5作为键2的值.因为m(1)完全解析为一个单独的映射到默认值,所以没有写入地图m.我们可以查看默认值:

default // Map(2 -> 5)

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

m // Map()

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

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

注意我们如何看到op:=> B’这意味着每次需要时,参数op都将被重新评估.这样我们可以在其中放置一个新的Map,并为每个无效的密钥分别创建一个Map.让我们来看看:

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

这里不需要默认值.

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

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

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

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

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

并检查是否添加:

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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读