You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为什么scala.collection.mutable.Map的withDefaultValue无法正确保留默认值?

Scala可变Map使用withDefaultValue后的行为解析

先看你给出的代码复现:

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)

核心原因拆解

  • withDefaultValue的作用逻辑:这个方法并没有改变Map的存储行为,它只是给Map绑定了一个固定的默认实例。当你访问不存在的键时,Map会直接返回这个预先创建好的实例,并不会将该键和默认实例添加到Map的内部存储中。而且所有不存在的键,返回的都是同一个实例。
  • Map为空的原因:调用m("a")时,仅仅是触发了默认值的返回,没有执行任何向Map中添加键值对的操作,所以Map的内部存储始终是空的,打印m或者m.keys自然看不到键"a"。
  • 再次访问能看到修改的原因:因为每次访问不存在的键,返回的都是同一个ListBuffer实例。第一次访问时拿到这个空实例,调用addOne("b")修改了它的内容;第二次访问时返回的还是这个已经被修改的实例,所以能看到ListBuffer(b)。

如果你想实现“访问不存在的键时自动添加到Map”

如果你的需求是访问不存在的键时,自动创建新的ListBuffer并添加到Map中,可以用withDefault(注意不是withDefaultValue)来实现:

val m = MMap[String, MList[String]]().withDefault { key =>
  val newList = MList[String]()
  m(key) = newList // 将新创建的ListBuffer添加到Map中
  newList
}

这样调用m("a")时,会自动创建新的ListBuffer并绑定到键"a",后续修改这个ListBuffer时,Map中也会保留对应的键值对。

内容的提问来源于stack exchange,提问作者Scoobie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 14:18:24