在地图中访问地图并处理可能的异常的有效方法

时间:2015-07-30 12:12:37

标签: scala hashmap nested

我有一个从JSON构建的某个地图,它有一些层次结构。例如:

"2015-05": {
    "129557": {          
        "123456": 3,
        "654321": 2,
        "143526": 1
     }
}

它存储为嵌套地图。我想要一个简单的方法来访问密钥。我可以在每个键上进行多次检查,然后查看它是否存在,然后为第二个键执行,依此类推。然而,这似乎很麻烦。我选择做这样的事情:

def getNumFromMap(key1: String, key2: Int, key3: String): Option[Int] ={
  try{
    map(key1)(key2).get(key3)
  }catch{
    case e: Exception => None
  }
}

此功能可能会被执行数百万次。使用try / catch会降低执行速度吗?是否有更好的方法来实现相同的更快?

4 个答案:

答案 0 :(得分:8)

使用for comprehension:

type MMMap[K1, K2, K3, V] = Map[K1, Map[K2, Map[K3, V]]]

def getFromMMMap[K1, K2, K3, V](
  mmmap: MMMap[K1, K2, K3, V], k1: K1, k2: K2, k3: K3
) : Option[V] =
  for {
    mmap <- mmmap.get(k1)
    map <- mmap.get(k2)
    v <- map.get(k3)
  } yield v

对于MMMap[String, Int, String, Int]

val mmmap = Map ("a" -> Map(1 -> Map("b" -> 2)))
scala> getFromMMMap(mmmap, "a", 1, "b")
res7: Option[Int] = Some(2)

答案 1 :(得分:1)

使用for表达式怎么样?

def getNumFromMap(key1: String, key2: Int, key3: String): Option[Int] ={
    for {
        m1 <- map.get(1)
        m2 <- m1.get(2)
        m3 <- m2.get(3)
    } yield m3
}

然而,如果不正确测量,很难说哪种方法更快。

答案 2 :(得分:1)

  def getNumFromMap(m: Map[String, Map[Int, Map[String, Int]]], key1: String, key2: Int, key3: String): Option[Int] = {
    m.get(key1).flatMap(_.get(key2)).flatMap(_.get(key3))
  }

答案 3 :(得分:0)

或者,单线版:

def get3[A, B, C, V](m: Map[A,Map[B,Map[C,V]]], a:A, b:B, c:C) : Option[V] =
  m.get(a).flatMap(_.get(b).flatMap(_.get(c)))

或者只是为了好玩,Pimp版

implicit final class Map3[A,B,C,V](val self : Map[A,Map[B,Map[C,V]]]) extends AnyVal {
  def get3(a:A, b:B, c:C) : Option[V] =
    self.get(a).flatMap(_.get(b).flatMap(_.get(c)))
}

然后:

val m : Map[Int, Map[String, Map[Boolean, Char]]] = Map(5 -> Map("a" -> Map(true -> 'c')))
m.get3(5, "a", true)