0

我为 scala 中的模式匹配编写了以下内容:

scala> val rowMap = Map("abc" -> null)
rowMap: scala.collection.immutable.Map[String,Null] = Map(abc -> null)

scala> val postgresKey = "abc"
postgresKey: String = abc

scala> val h2Key = "xyz"
h2Key: String = xyz

建议选项:

scala> (rowMap.get(postgresKey).map(_.asInstanceOf[String]) , rowMap.get(h2Key).map(_.asInstanceOf[String])) match
     |       {
     |         case (Some(value), _) if (value != null && value.trim.nonEmpty) => value
     |         case (None, Some(value)) if (value != null && value.trim.nonEmpty) => value
     |         case (_ , _) => "0.0"
     |       }
res9: String = 0.0

我的代码:

scala> (rowMap.get(postgresKey).map(_.asInstanceOf[String]) , rowMap.get(h2Key).map(_.asInstanceOf[String])) match
     |       {
     |         case (Some(value), _) if (value != null ) => if (value.trim.nonEmpty) value else "0.0"
     |         case (None, Some(value)) if (value != null ) => if (value.trim.nonEmpty) value else "0.0"
     |         case (_ , _) => "0.0"
     |       }  
res10: String = 0.0

建议的选项是否比我的代码有任何性能优势。我知道它会在它看到 a 的那一刻&&停止比较。因此,我们节省了 1 个比较。value.trim.nonEmptynull

我确实明白阅读起来也更干净。在建议的方法中还有什么更好的方法吗?

编辑 1:我被告知要避免使用null. 然而,它是来自 anorm's 的输入defaultParser。由于该场景难以复制,因此我给出了上面的示例。就我而言,单元测试在 H2 中,实际数据库是 postgres。

以下是代码片段:

            val anormQuery = SQL(query)
            // map the anorm Row as per the input params, differentiate into aggregated and group cols
            val tmp = anormQuery.as(anormQuery.defaultParser.*)

            logger.info(" Printing the result set object " + tmp.toString())

            val finalSqlResultset = tmp.map(row ⇒ {

              // Anorm row.asMap has this behaviour that it adds either a leading dot(.) or <tablename>. in front of the map keys (the columns/alias in sql) based on whether it is H2 or Postgres

              val rowMap = for ((k, v) ← row.asMap) yield (k, v)
              logger.info("Print the resultSet as map : " + rowMap.toString())


              val aggregates = expressionsToAggregate.map(input ⇒ {
                val (anormKey, postgresKey) = doesColumnHaveAlias.get(input.alias.getOrElse("UnknownAlias")).getOrElse(("Unknown", "Unknown"))
                //
                val aggResult = AggregatedValue(
                  input.alias.get,
                  (rowMap.get(postgresKey).map(_.asInstanceOf[String]), rowMap.get(anormKey).map(_.asInstanceOf[String])) match {
                    case (Some(value), _) if (value != null && value.trim.nonEmpty) ⇒ value
                    case (None, Some(value)) if (value != null && value.trim.nonEmpty) ⇒ value
                    case (_, _) ⇒ "0.0"
                  })
                logger.info("## TRACE 1 ##" + aggResult)
                aggResult
              })
})
4

1 回答 1

4

首先,不要使用 nulls。曾经。做吧val rowMap = Map("abc" -> "")

或者更好的是,根本不要将垃圾放入地图中(无论如何你都在过滤掉它!)。

其次,既然你提到了可读性,看起来你正在寻找这样的东西:

 rowMap.get(postgresKey).filterNot(_.trim.isEmpty)
  .orElse(rowMap.get(h2Key).filerNot(_.trim.isEmpty))
  .getOrElse("0.0")

最后,为了回答您的问题,您展示的两个版本并不相同。第一个做我上面做的。第二个是这样的:

 rowMap.get(postgresKey).orElse(rowMap.get(h2Key))
   .filterNot(_.trim.isEmpty)
   .getOrElse("0.0")

在前一种情况下,设置postgresKey""等同于根本不设置它,在这种情况下你总是会得到值h2Key。在后一种情况下,如果postgresKey设置为""您将得到“0.0”,无论h2Key设置什么。

所以,行为是不同的,这取决于你真正需要哪一个。

如果第一种行为是你需要的,也可以这样写:

Some(rowMap.filterValues(_.trim.nonEmpty)).flatMap { case m => 
   m.get(postrgesKey) orElse m.get(h2Key)
}.getOrElse("0.0")

或者,如果您听取我的建议并决定一开始就不将垃圾放入地图,您也可以松开过滤器:

roMap.get(postrgesKey) orElse rowMap.get(h2Key) getOrElse "0.0"
于 2020-01-23T12:46:03.330 回答