访问地图内部地图和处理可能的异常的有效方法

Efficient way to access maps inside maps and handle possible exceptions

我有一张根据 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 会减慢执行速度吗?有没有更快的更好的方法来完成同样的事情?

使用 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
}

但是,如果不正确衡量,很难说哪种方法更快。

使用 a 进行理解:

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)
  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))
  }

或者,单行版本:

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)))

或者只是为了好玩,皮条客版本

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)