开发者

Is there a way to get a Scala HashMap to automatically initialize values?'

I thought it could be done as follows

val hash = new HashMap[String, ListBuffer[Int]].withDefaultValue(ListBuffer())
has开发者_Python百科h("A").append(1)
hash("B").append(2)
println(hash("B").head)

However the above prints the unintuitive value of 1. I would like

hash("B").append(2)

To do something like the following behind the scenes

if (!hash.contains("B")) hash.put("B", ListBuffer())


Use getOrElseUpdate to provide the default value at the point of access:

scala> import collection.mutable._
import collection.mutable._

scala> def defaultValue = ListBuffer[Int]()
defaultValue: scala.collection.mutable.ListBuffer[Int]

scala> val hash = new HashMap[String, ListBuffer[Int]]
hash: scala.collection.mutable.HashMap[String,scala.collection.mutable.ListBuffer[Int]] = Map()

scala> hash.getOrElseUpdate("A", defaultValue).append(1)

scala> hash.getOrElseUpdate("B", defaultValue).append(2)

scala> println(hash("B").head)
2


withDefaultValue uses exactly the same value each time. In your case, it's the same empty ListBuffer that gets shared by everyone.

If you use withDefault instead, you could generate a new ListBuffer every time, but it wouldn't get stored.

So what you'd really like is a method that would know to add the default value. You can create such a method inside a wrapper class and then write an implicit conversion:

class InstantiateDefaults[A,B](h: collection.mutable.Map[A,B]) {
  def retrieve(a: A) = h.getOrElseUpdate(a, h(a))
}
implicit def hash_can_instantiate[A,B](h: collection.mutable.Map[A,B]) = {
  new InstantiateDefaults(h)
}

Now your code works as desired (except for the extra method name, which you could pick to be shorter if you wanted):

val hash = new collection.mutable.HashMap[
  String, collection.mutable.ListBuffer[Int]
].withDefault(_ => collection.mutable.ListBuffer())

scala> hash.retrieve("A").append(1)

scala> hash.retrieve("B").append(2)

scala> hash("B").head
res28: Int = 2

Note that the solution (with the implicit) doesn't need to know the default value itself at all, so you can do this once and then default-with-addition to your heart's content.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜