当需要跳过没有默认值的不存在的键时,如何处理Map中找不到的键?

yjghlzjz  于 2021-07-14  发布在  Java
关注(0)|答案(1)|浏览(238)

我有一组字符串,并使用它作为键值从Map中获取jvalue:

val keys: Set[String] = Set("Metric_1", "Metric_2", "Metric_3", "Metric_4")
val logData: Map[String, JValue] = Map("Metric_1" -> JInt(0), "Metric_2" -> JInt(1), "Metric_3" -> null)

在下面的方法中,我解析每个度量的值。首先获取所有值,然后过滤以除去空值,然后将现有值转换为布尔值。

val metricsMap: Map[String, Boolean] = keys
      .map(k => k -> logData(k).extractOpt[Int]).toMap
      .filter(_._2.isDefined)
      .collect {
        case (str, Some(0)) => str -> false
        case (str, Some(1)) => str -> true
      }

我遇到了一个问题 keys 在中找不到 logData Map。所以我得到了一个 java.util.NoSuchElementException: key not found: Metric_4 .
这是我用的 extractOpt 从json中提取值,不需要默认值。所以很可能 extractOrElse 不会有帮助,因为我只需要获取现有键的值并跳过不存在的键。
当钥匙不在保险箱中时,处理案件的正确方法是什么 logData Map?
upd:我已经达到了预期的效果 .map(k => k -> apiData.getOrElse(k, null).extractOpt[Int]).toMap . 但是仍然不确定这是最好的方法。

igetnqfo

igetnqfo1#

值是json是一个危险的问题——引发异常的是缺少的键。有一个方法叫做 get 从封装在选项中的Map中检索值。如果我们使用 Int 作为我们的价值观:

val logData = Map("Metric_1" -> 1, "Metric_2" -> 0, "Metric_3" -> null)
keys.flatMap(k => logData.get(k).map(k -> _)).toMap

> Map(Metric_1 -> 1, Metric_2 -> 0, Metric_3 -> null)

使用 flatMap 而不是 map 意味着打开 Some 结果并删除 None s。现在,如果我们回到你的实际例子,我们有另一层,平面图将消除 Metric_3 -> null 项目:

keys.flatMap(k => logData.get(k).flatMap(_.extractOpt[Int]).map(k -> _)).toMap

您也可以使用 for 理解力:

(for {
   k <- keys
   jv <- logData.get(k)
   v <- jv.extractOpt[Int]
 } yield k -> v).toMap

我曾经 Success 以及 Failure 代替json值,以避免必须使用json4s设置shell来制作示例:

val logData = Map("Metric_1" -> Success(1), "Metric_2" -> Success(0), "Metric_3" -> Failure(new RuntimeException()))
scala> for {
 | k <- keys
 | v <- logData.get(k)
 | r <- v.toOption
 | } yield k -> r
 res2: scala.collection.immutable.Set[(String, Int)] = Set((Metric_1,1), (Metric_2,0))

相关问题