首页 > 解决方案 > Scala - 模式匹配布尔值和默认值时无法访问的代码

问题描述

我有一个Map[String, Boolean]包含各种 Metrics 数据和一个单独Seq[String]的包含metricKeys.

问题是 Map 可能不包含所有内容,metricKeys但我还需要保留有关不存在值的信息。我试图通过使用来解决这个问题.getOrElse。我预计List[String]带有度量值的结果将包含“Y”代表值true,“N”代表值false和“”代表null值。

但是我收到一个警告:unreachable code case _ => StringUtils.EMPTY。什么是正确匹配默认值的正确方法?

def parseMetrics(metric: Metric): List[String] = {
    import scala.collection.JavaConverters._
    val metricKeys: Seq[String] = getMetricKeys
    val matricsData = metric.transactionMap.asScala

metricKeys.map(key => key -> matricsData.getOrElse(key, null))
      .toMap.values.map(Predef.Boolean2boolean).collect  {
      case true => "Y"
      case false => "N"
      case _ => StringUtils.EMPTY
    }.toList
}

标签: javascalacollectionspattern-matching

解决方案


我假设这是对这个问题的跟进,并且matricsData有一个类似的类型Map[String, java.lang.Boolean]

那么问题是当它的参数是 时,Predef.Boolean2boolean从装箱 Java 布尔值到 Scala 布尔值的转换会返回,所以如果你想区分 true、false 和的值,你需要在转换之前进行(无论是否转换是明确的,就像这里一样)。falsenullnulljava.lang.Boolean

但是,有更好的方法来解决这个问题,如下所示:

metricKeys.map { key =>
  matricsData.get(key) match {
    case Some(value) => if (value) "Y" else "N"
    case None        => StringUtils.EMPTY
  }
}

或者使用foldonOption而不是模式匹配:

metricKeys.map { key =>
  matricsData.get(key).fold(StringUtils.EMPTY) { value =>
    if (value) "Y" else "N"
  }
}

或者先转换映射值,然后查找所有键:

val asYN: Map[String, String] = matricsData.mapValues { value =>
  if (value) "Y" else "N"
}

metricKeys.map(key => asYN.getOrElse(key, StringUtils.EMPTY))

您选择哪种方法取决于个人喜好,但其中任何一种方法都比使用盒装 Java 布尔值对某种三向真假或缺失数据建模要好。


推荐阅读