Я использую много вложенных карт, например, Map [Int, Map [String, Set [String]]], и я хотел бы, чтобы новые Карты, Наборы и т. Д. Создавались автоматически при доступе кновый ключНапример, что-то вроде следующего:
val m = ...
m(1992)("foo") += "bar"
Обратите внимание, что я не хочу использовать здесь getOrElseUpdate, если мне не нужно, потому что он становится довольно многословным, когда вы вложили карты и затемняет то, что на самом деле происходит вкод:
m.getOrElseUpdate(1992, Map[String, Set[String]]()).getOrElseUpdate("foo", Set[String]()) ++= "bar"
Так что я переопределяю метод «по умолчанию» в HashMap.Я попробовал два способа сделать это, но ни один не вполне удовлетворителен.Моим первым решением было написать метод, который создал карту, но, похоже, мне все еще нужно указать полный вложенный тип карты, когда я объявляю переменную, или что-то не работает:
scala> def defaultingMap[K, V](defaultValue: => V): Map[K, V] = new HashMap[K, V] { | override def default(key: K) = {
| val result = defaultValue
| this(key) = result
| result
| }
| }
defaultingMap: [K,V](defaultValue: => V)scala.collection.mutable.Map[K,V]
scala> val m: Map[Int, Map[String, Set[String]]] = defaultingMap(defaultingMap(Set[String]()))
m: scala.collection.mutable.Map[Int,scala.collection.mutable.Map[String,scala.collection.mutable.Set[String]]] = Map()
scala> m(1992)("foo") += "bar"; println(m)
Map(1992 -> Map(foo -> Set(bar)))
scala> val m = defaultingMap(defaultingMap(Set[String]()))
m: scala.collection.mutable.Map[Nothing,scala.collection.mutable.Map[Nothing,scala.collection.mutable.Set[String]]] = Map()
scala> m(1992)("foo") += "bar"; println(m)
<console>:11: error: type mismatch;
found : Int(1992)
required: Nothing
m(1992)("foo") += "bar"; println(m)
^
Мой второйРешением было написать фабричный класс с методом, и таким образом я должен объявить каждый тип только один раз.Но затем каждый раз, когда я хочу новую карту со значением по умолчанию, мне нужно как создать экземпляр фабричного класса, так и затем вызвать метод, который все еще кажется немного многословным:
scala> class Factory[K] {
| def create[V](defaultValue: => V) = new HashMap[K, V] {
| override def default(key: K) = {
| val result = defaultValue
| this(key) = result
| result
| }
| }
| }
defined class Factory
scala> val m = new Factory[Int].create(new Factory[String].create(Set[String]()))
m: scala.collection.mutable.HashMap[Int,scala.collection.mutable.HashMap[String,scala.collection.mutable.Set[String]]] = Map()
scala> m(1992)("foo") += "bar"; println(m)
Map(1992 -> Map(foo -> Set(bar)))
Мне бы очень хотелось получить что-тотак просто, как это:
val m = defaultingMap[Int](defaultingMap[String](Set[String]()))
Кто-нибудь видит способ сделать это?