2

How do I avoid the initialization (lines 5 and 6) here?

import scala.collection._
def newHash = mutable.Map[String,String]()
def newHoH = mutable.Map[String,mutable.Map[String,String]]()
var foo = mutable.Map[String,mutable.Map[String,mutable.Map[String,String]]]()
foo("bar") = newHoH          //line 5
foo("bar")("baz") = newHash  //line 6
foo("bar")("baz")("whee") = "duh"

I tried withDefaultValue with a simpler example but obviously I did it wrong:

/***
scala> var foo = mutable.Map[String,mutable.Map[String,String]]().withDefaultValue(mutable.Map(""->""))
foo: scala.collection.mutable.Map[String,scala.collection.mutable.Map[String,String]] = Map()

scala> foo("bar")("baz") = "duh"
scala> foo("b")("baz") = "der"
scala> foo("bar")("baz")
res7: String = der
*/
4

1 回答 1

0

withDefault方法在这里行不通。以这种方式创建的 AMap每次没有键时都会返回一个新映射,因此调用mymap("foo")("bar") = "ok"会将“ok”分配给临时创建的映射,但是下次调用时mymap("foo")("bar"),不存在的"foo"mymap将导致创建一个新映射,这将不包含映射"foo" -> "bar"

相反,请考虑创建匿名地图。我展示了一个只有 1 个嵌套的解决方案:

‡ scala-version 2.10.1
Welcome to Scala version 2.10.1 (Java HotSpot(TM) Server VM, Java 1.7.0_21).
Type in expressions to have them evaluated.
Type :help for more information.

scala> import collection._
import collection._

scala> :paste
// Entering paste mode (ctrl-D to finish)

def newHash = mutable.Map[String,String]().withDefault(_ => "")

def newHoH = new mutable.Map[String,mutable.Map[String,String]]() {
  val m = mutable.Map[String, mutable.Map[String, String]]()
  def +=(kv: (String, mutable.Map[String, String])) = { m += kv; this }
  def -=(k: String) = { m -= k; this }
  def get(k: String) = m.get(k) match {
    case opt @ Some(v) => opt
    case None =>
      val v = newHash
      m(k) = v
      Some(v)
  }
  def iterator = m.iterator
}

// Exiting paste mode, now interpreting.

newHash: scala.collection.mutable.Map[String,String]
newHoH: scala.collection.mutable.Map[String,scala.collection.mutable.Map[String,String]]{val m: scala.collection.mutable.Map[String,scala.collection.mutable.Map[String,String]]}

scala> val m = newHoH
m: scala.collection.mutable.Map[String,scala.collection.mutable.Map[String,String]]{val m: scala.collection.mutable.Map[String,scala.collection.mutable.Map[String,String]]} = Map()

scala> m("foo")("bar") = "ok"

scala> m("foo")("bar")
res1: String = ok
于 2013-10-21T02:31:21.633 回答