17

immutable.Map 实例的 getOrElseUpdate 的惯用方式是什么?我使用下面的代码片段,但它似乎冗长且效率低下

var map = Map[Key, Value]()

def foo(key: Key) = {
  val value = map.getOrElse(key, new Value)
  map += key -> value
  value
}
4

4 回答 4

15

我可能会实现这样的getOrElseUpdated方法:

def getOrElseUpdated[K, V](m: Map[K, V], key: K, op: => V): (Map[K, V], V) =
  m.get(key) match {
    case Some(value) => (m, value)
    case None => val newval = op; (m.updated(key, newval), newval)
  }

m如果有一个映射,则返回原始映射key或添加了映射的另一个映射key -> op。该方法的定义与 ofgetOrElseUpdate类似mutable.Map

于 2011-04-30T06:48:19.623 回答
9

让我总结一下你的问题:

  • 您想在不可变数据结构上调用方法
  • 您希望它返回一些值重新分配var
  • 因为数据结构是不可变的,所以你需要
    • 返回一个新的不可变数据结构,或者
    • 使用提供的闭包在方法内部进行赋值

所以,要么你的签名看起来像

def getOrElseUpdate(key: K): Tuple2[V, Map[K,V]]
//... use it like
val (v, m2) = getOrElseUpdate(k)
map = m2

或者

def getOrElseUpdate(key: K, setter: (Map[K,V]) => Unit): V
//... use it like
val v = getOrElseUpdate(k, map = _)

如果您可以使用其中一种解决方案,则可以使用隐式转换添加自己的版本,但仅从签名来看,我认为这些都不属于标准库。

于 2010-12-08T15:20:58.023 回答
8

没有这样的方法 - 当您获得地图值时,地图突变(更新)是一种副作用(这与编程的不变性/功能风格相矛盾)。

当您想使用默认值创建一个新的不可变映射时,如果指定键的另一个值不存在,您可以执行以下操作:

map + (key -> map.getOrElse(key, new Value)) 
于 2010-12-08T10:02:51.030 回答
2

为什么不使用withDefault或者withDefaultValue如果你有一个不可变的地图?

于 2010-12-08T14:10:20.160 回答