有时我使用Map
作为记忆缓存。使用可变地图,我使用getOrElseUpdate
:
mutableMap.getOrElseUpdate(key, {
val value = <compute the value>
value
})
不可变地图没有getOrElseUpdate
。所以我想这样做
immutableMap.getOrElse(key, {
val value = <compute the value>
immutableMap += key -> value
value
})
这似乎在实践中起作用,我有充分的理由认为它在理论上有效,而且它的可读性或多或少 - 出于某些原因,这是一个可怕的想法我错过了吗?
我考虑的其他选择
immutableMap.get(key) match {
case Some(value) => value
case None =>
val value = <compute the value>
immutableMap += key -> value
value
}
没有太大的不同,而且更麻烦,或
if (immutableMap.contains(key)) {
immutableMap(key)
} else {
val value = <compute the value>
immutableMap += key -> value
value
}
这是最愚蠢的,可能是最不恰当的。
原则上我宁愿不寻求使用帮助器来返回值和更新后的地图的解决方案,除非它是无可争议的优越方式。
答案 0 :(得分:1)
当然,除了一个小问题似乎是合理的......它没有更新你的收藏!如果您正在使用不可变映射,那么该映射是不可变的。永远不能改变它。
事实上,Scala集合中的不可变Map甚至没有定义app.use(bodyParser.json({limit: '50mb'}));
app.use(bodyParser.urlencoded({limit: '50mb', extended: true}));
方法,请参阅immutable.Map。使用&#34;追加&#34;的所有方法或者&#34;添加&#34; Map的新值实际上会返回 new Map。因此,对于您上面编写的内容进行编译,您不得不使用不可变的内容。
要使用不可变地图执行此操作,您需要使用+=
并将var
替换为新地图(这可能会导致线程问题)或者您有采用State Monad类型模式,不仅返回新值,还返回新Map。
var
答案 1 :(得分:0)
我唯一的建议(关于您选择var
而不是mutable.Map
或Java ConcurrentMap
的原因)是将其包装到DSL中,例如:
case class Mutable[K,V](var m: Map[K,V]) {
def orElseUpdate(key: K, compute: => V) = m.getOrElse(key, {
val value = compute
m += key -> value
value
})
}
scala> val a = Mutable(Map(1 -> 2))
a: Mutable[Int,Int] = Mutable(Map(1 -> 2))
scala> a.orElseUpdate(2, 4)
res10: Int = 4
scala> a.orElseUpdate(2, 6)
res11: Int = 4
scala> a.orElseUpdate(3, 6)
res12: Int = 6
另一个选项(如果你的计算是轻量级的)只是:
m += key -> m.getOrElse(key, compute)
m(key)
示例:
scala> var m = Map(1 -> 2)
m: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2)
scala> m += 3 -> m.getOrElse(3, 5)
scala> m
res1: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2, 3 -> 5)
scala> m += 3 -> m.getOrElse(3, 5)
scala> m
res3: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2, 3 -> 5)
scala> m += 3 -> m.getOrElse(3, 6)
scala> m
res5: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2, 3 -> 5)
您也可以将其包装到DSL中:
implicit class RichMap[K,V](m: Map[K,V]) {
def kvOrElse(k: K, v: V) = k -> m.getOrElse(k, v)
}
scala> m += m.kvOrElse(3, 7)
scala> m
res7: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2, 3 -> 5)
scala> m += m.kvOrElse(4, 7)
scala> m
res9: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2, 3 -> 5, 4 -> 7)