Scala:使用具有默认值的 HashMap

Posted

技术标签:

【中文标题】Scala:使用具有默认值的 HashMap【英文标题】:Scala: Using HashMap with a default value 【发布时间】:2011-04-08 14:40:45 【问题描述】:

我有一个可变的 HashMap,想像使用默认字典一样使用它。显而易见的方法似乎是使用 getOrElse 并每次都提供默认值作为第二个值。然而,这在我的用例中似乎有点不雅,因为默认值没有改变。

var x = HashMap(1 -> "b", 2 -> "a", 3 -> "c")

println(x.getOrElse(4, "_")
println(x.getOrElse(5, "_"))
// And so on...
println(x.getOrElse(10, "_"))

有什么方法可以创建一个 HashMap(或类似的类),以便尝试访问未定义的键返回一个在创建 HashMap 时设置的默认值?我注意到 HashMap.default 只是设置为抛出异常,但我想知道这是否可以更改...

【问题讨论】:

对于任何偶然发现这个问题的人,missingfaktor 的帖子正确地指出“Scala 2.9.1. mutable.Map 带有 withDefaultValue 方法” 【参考方案1】:

哇,在我在这里发布我的最后一个答案一年后,我碰巧访问了这个帖子。 :-)

Scala 2.9.1。 mutable.Map 带有 withDefaultValue 方法。 REPL 会话:

scala> import collection.mutable
import collection.mutable

scala> mutable.Map[Int, String]().withDefaultValue("")
res18: scala.collection.mutable.Map[Int,String] = Map()

scala> res18(3)
res19: String = ""

【讨论】:

我担心这个性能 - mutable.Map 使用 HashMaps 吗?它的表现如何? WithDefault 仅覆盖default 方法(因此仅影响apply)并在未找到密钥时返回默认值。其他所有内容都发送到底层Map【参考方案2】:
scala> val x = HashMap(1 -> "b", 2 -> "a", 3 -> "c").withDefaultValue("-")
x: scala.collection.immutable.Map[Int,java.lang.String] = Map((1,b), (2,a), (3,c))

scala> x(3)
res0: java.lang.String = c

scala> x(5)
res1: java.lang.String = -

编辑:

对于mutable.HashMap,您可以执行以下操作:

scala> import collection.mutable
import collection.mutable

scala> val x = new mutable.HashMap[Int, String] 
     |   override def apply(key: Int) = super.get(key) getOrElse "-"
     | 
x: scala.collection.mutable.HashMap[Int,String] = Map()

scala> x += (1 -> "a", 2 -> "b", 3 -> "c")
res9: x.type = Map((2,b), (1,a), (3,c))

scala> x(2)
res10: String = b

scala> x(4)
res11: String = -

可能有更好的方法来做到这一点。等待其他人回应。

【讨论】:

@PythonPower:您没有在原始问题中指定使用mutable.HashMap。我不知道如何使用mutable.HashMap。我得研究一下 API。 是的,对不起,我没有具体说明——我已经编辑了我的问题,以便现在清楚。【参考方案3】:

试试这个:

import collection.mutable.HashMap
val x = new HashMap[Int,String]()   override def default(key:Int) = "-" 
x += (1 -> "b", 2 -> "a", 3 -> "c")

然后:

scala> x(1)
res7: String = b

scala> x(2)
res8: String = a

scala> x(3)
res9: String = c

scala> x(4)
res10: String = -

【讨论】:

+1。想知道为什么 mutable.HashMap 不提供像 immutable.HashMap 这样的 withDefaultValue 方法。 这是一种可怕的语法,但它确实有效。也许应该将可变 HashMap 缺少 withDefaultValue 报告为错误? 有一个“!!! todo: 移动到通用地图?”在scala-lang.org/api/current/scala/collection/immutable/Map.html 中的相邻withDefault 中发表评论。因此,这可能并不过分。 scala-user 邮件列表可能是查询此问题并查看是否应报告错误的好地方。 @PythonPower 已提交增强票证lampsvn.epfl.ch/trac/scala/ticket/3829。 感谢您的报告!很高兴看到 Scala 得到如此积极的改进。【参考方案4】:

我更像是一个 java 人...但是如果 getOrElse 不是最终的,你为什么不扩展 HasMap 并提供这样的东西:

override def getOrElse(k: Int, default: String) = 
  return super.getOrElse(k,"_")

注意:语法可能搞砸了,但希望你能明白这一点

【讨论】:

是的,我认为可以扩展HashMap。在这种情况下,更改 HashMap.default 方法以返回我想要的可能会更容易。构造函数可以采用默认值,而 HashMap.default 方法只会返回该值。不过,我希望有一种更简单的方法。 我们不这样做是因为它比 getOrElse 更复杂 - 它的灵活性较低,不必要地冗长,如果你必须这样做,那么它是一个强大的表明你应该使用一些高级抽象,比如 monoids。

以上是关于Scala:使用具有默认值的 HashMap的主要内容,如果未能解决你的问题,请参考以下文章

在 pyspark 的 Scala UDF 中使用默认参数值?

groovy中具有默认值的命名参数

使用 Dapper 插入具有默认值的表

在 SpringBoot 中将 yaml 映射到对象 hashmap

React/Redux 中具有默认值的文本输入

JavaScriptSerializer 可以排除具有空值/默认值的属性吗?