如何在Scala中创建以下地图映射

时间:2015-04-08 15:06:02

标签: scala scala-collections

我是Scala新手:如何创建以下地图"地图地图"在斯卡拉:

"Outer" map
+-------------------------+-------------------------------+
|           Key           |             Value             |
+-------------------------+-------------------------------+
| (employeID, currencyID) | (valueDate, set of CashFlow)  |
+-------------------------+-------------------------------+

"外部"中的值地图也是一张地图:

"Inner" map
+-----------+------------------+
|    Key    |      Value       |
+-----------+------------------+
| valueDate | set of CashFlow  |
+-----------+------------------+

具有以下类型:

  • employeeID:Int
  • currencyID:Int
  • valueDate:java.util.Date
  • 设置CashFlow:设置[com.company.CashFlow]

以下不会编译(需要覆盖+ =, - =等):

myMap = new mutable.HashMap[(Int, Int), java.util.TreeMap[Date, mutable.Set[CashFlow]] with mutable.MultiMap[Date, CashFlow].withDefaultValue(new util.TreeMap[Date, mutable.Set[CashFlow]] with mutable.MultiMap[Date, CashFlow]

要求:

  • 地图必须是可变的
  • 按valueDate排序
  • 对于一个valueDate,我可以有多个现金流
  • 我想避免在(employeeID,currencyID)上检查密钥是否存在,即如果密钥不存在,myMap(emp1, ccy1).addBinding(date1, cashFlow1)不应该失败。 相反,它应该自动创建一个新的空排序MultiMap并用(date1,cashFlow1)
  • 初始化它

1 个答案:

答案 0 :(得分:3)

您可以在不MultiMap的情况下创建它:

import scala.collection.mutable._, JavaConverters._, java.util.TreeMap

val myMap = new mutable.HashMap[(Int, Int), mutable.Map[Date, Set[CashFlow]]]{ 
    override def apply(k: (Int, Int)) = 
       getOrElseUpdate(k, new TreeMap[Date, mutable.Set[CashFlow]].asScala) 
}
myMap: scala.collection.mutable.Map[(Int, Int),scala.collection.mutable.Map[java.util.Date,scala.collection.mutable.Set[CashFlow]]] = Map()
需要

override def applywithDefaultValue将始终返回相同的值。

也可以使用标准包装器从java MultiMap创建TreeMap

import scala.collection.convert.Wrappers._

//This wrapper will hold your Java's TreeMap inside, and delegate all operations to it
scala> def newTreeMultiMap[K, V]: MultiMap[K, V] = new JMapWrapper(new TreeMap[K, Set[V]]) with MultiMap[K, V]
newTreeMultiMap: [K, V]=> scala.collection.mutable.MultiMap[K,V]

scala> val myMap = new HashMap[(Int, Int), MultiMap[Int, String]]{ override def apply(k: (Int, Int)) = getOrElseUpdate(k, newTreeMultiMap[Int, String]) }
myMap: scala.collection.mutable.Map[(Int, Int),scala.collection.mutable.MultiMap[java.util.Date,CashFlow]] = Map()

我认为它应该在标准库中,但没有找到。

示例(我使用Int代替Date来表明订购有效):

scala> val myMap = new HashMap[(Int, Int), MultiMap[Int, String]]{ override def apply(k: (Int, Int)) = getOrElseUpdate(k, newTreeMultiMap[Int, String]) }
myMap: scala.collection.mutable.Map[(Int, Int),scala.collection.mutable.MultiMap[Int,String]] = Map()

scala> myMap(0 -> 0).addBinding(4, "aaa") //no exceptions on myMap(0 -> 0) with empty Map
res27: scala.collection.mutable.MultiMap[Int,String] = Map(4 -> Set(aaa))

scala> myMap(0 -> 0).addBinding(2, "aaa") //should be before 4
res28: scala.collection.mutable.MultiMap[Int,String] = Map(2 -> Set(aaa), 4 -> Set(aaa))

scala> myMap(0 -> 0).addBinding(5, "aaa") //should be after 4
res29: scala.collection.mutable.MultiMap[Int,String] = Map(2 -> Set(aaa), 4 -> Set(aaa), 5 -> Set(aaa))

scala> myMap(0 -> 0).addBinding(4, "bbb")
res30: scala.collection.mutable.MultiMap[Int,String] = Map(2 -> Set(aaa), 4 -> Set(aaa, bbb), 5 -> Set(aaa))

scala> myMap(0 -> 0).toList //finally use the order
res31: List[(Int, scala.collection.mutable.Set[String])] = List((2,Set(aaa)), (4,Set(aaa, bbb)), (5,Set(aaa)))

scala> myMap(0 -> 1).addBinding(2, "aaa") 
res18: scala.collection.mutable.MultiMap[Int,String] = Map(2 -> Set(aaa))