Есть ли способ получить Scala HashMap для автоматической инициализации значений? - PullRequest
4 голосов
/ 22 сентября 2011

Я думал, что это можно сделать следующим образом

val hash = new HashMap[String, ListBuffer[Int]].withDefaultValue(ListBuffer())
hash("A").append(1)
hash("B").append(2)
println(hash("B").head)

Однако вышеприведенное выводит неинтуитивное значение 1. Я бы хотел

hash("B").append(2)

Чтобы сделать что-то вроде следующего засцены

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

Ответы [ 2 ]

10 голосов
/ 22 сентября 2011

Используйте getOrElseUpdate для предоставления значения по умолчанию в точке доступа:

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
8 голосов
/ 22 сентября 2011

withDefaultValue использует одно и то же значение каждый раз.В вашем случае это один и тот же пустой ListBuffer, который будет доступен всем.

Если вы используете вместо него withDefault, вы можете каждый раз генерировать новый ListBuffer, но он не будет сохранен.

Итак, вам действительно нужен метод, который знает, как добавить значение по умолчанию.Вы можете создать такой метод внутри класса-оболочки и затем написать неявное преобразование:

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)
}

Теперь ваш код работает так, как вам нужно (за исключением дополнительного имени метода, которое вы можете выбрать более коротким, если хотите)):

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

Обратите внимание, что решению (с неявным) вообще не нужно знать значение по умолчанию, так что вы можете сделать это один раз, а затем добавить по умолчанию с добавлением вашего сердца..

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...