我发现自己使用了很多嵌套映射,例如Map [Int,Map [String,Set [String]]],我希望在访问新密钥时自动创建新的地图,集等.例如以下内容:
val m = ...
m(1992)("foo") += "bar"
Run Code Online (Sandbox Code Playgroud)
请注意,如果我不需要,我不想在这里使用getOrElseUpdate,因为当你有嵌套的地图并且隐藏代码中实际发生的事情时,它会变得非常冗长:
m.getOrElseUpdate(1992, Map[String, Set[String]]()).getOrElseUpdate("foo", Set[String]()) ++= "bar"
Run Code Online (Sandbox Code Playgroud)
所以我重写了HashMap的"默认"方法.我尝试了两种方法,但都没有完全令人满意.我的第一个解决方案是编写一个创建地图的方法,但是当我声明变量或事情不起作用时,似乎我仍然必须指定完整的嵌套Map类型:
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))) …Run Code Online (Sandbox Code Playgroud) 我正在尝试定义一个类,该类将包含一个 Set 字段,并且希望能够直接从容器类中操作这个集合:
case class MyClass(prop: String) extends TraversableLike[Int,MyClass] {
private def mySet: Set[Int]() = Set()
override def foreach[U](f: Int => U) = data.foreach[U](f)
override def newBuilder: Builder[Int, MyClass] =
new ArrayBuffer[Int] mapResult (a => MyClass(prop, a.toSet))
implicit def canBuildFrom: CanBuildFrom[MyClass, Int, MyClass] =
new CanBuildFrom[MyClass, Int, MyClass] {
def apply(): Builder[Int, MyClass] = newBuilder
def apply(from: MyClass): Builder[Int, MyClass] = newBuilder
}
}
Run Code Online (Sandbox Code Playgroud)
我希望能够做到
var obj = MyClass("hello")
obj += 1
obj = obj map (_+1)
Run Code Online (Sandbox Code Playgroud)
第一条指令 (obj+= 1) …