我写了一种解析Metrics数据的方法,首先遇到了java.util.Map
这是transactionMap类型的问题。我使用JavaConverters解决了它。
def parseMetrics(metric: Metric) = {
import scala.collection.JavaConverters._
metric.transactionMap.asScala.values.map {
case false => "N"
case true => "Y"
}.toList
但是在此之后,在模式匹配真值和假值时出现错误:pattern type is incompatible with expected type, found: Boolean, required: java.lang.Boolean
据我了解,Scala不会链接两个隐式转换。有没有办法使用JavaConverters修复它?
答案 0 :(得分:5)
另一个答案提供了解决此问题的合理方法,但没有说明您为何会遇到该问题或它提出的方法是如何工作的。
Scala标准库确实提供了从java.lang.Boolean
到scala.Boolean
的隐式转换,您可以通过在REPL中使用reify
对使用Java布尔值的某些代码进行解糖来实际看到在需要Scala布尔值的情况下:
scala> val x: java.lang.Boolean = true
x: Boolean = true
scala> import scala.reflect.runtime.universe.reify
import scala.reflect.runtime.universe.reify
scala> reify(if (x) 1 else 0)
res0: reflect.runtime.universe.Expr[Int] =
Expr[Int](if (Predef.Boolean2boolean($read.x))
1
else
0)
问题在于,仅尝试将java.lang.Boolean
值与true
或false
进行匹配不足以触发转换。您可以通过定义自己的类型来进行检查,以确保您确切地知道正在进行哪些转化:
scala> case class Foo(i: Int); case class Bar(i: Int)
defined class Foo
defined class Bar
scala> implicit def foo2bar(foo: Foo): Bar = Bar(foo.i)
foo2bar: (foo: Foo)Bar
scala> Foo(100) match { case Bar(x) => x }
<console>:17: error: constructor cannot be instantiated to expected type;
found : Bar
required: Foo
Foo(100) match { case Bar(x) => x }
^
这是语言设计的决定。可能有可能在这些情况下应用隐式转换,但是也可能有一个很好的理由,那就是它们不(我不知道任何相关的讨论或问题,但事实并非如此)。并不意味着它们不存在。
Andy解决方案起作用的原因是java.lang.Boolean
处于编译器期望scala.Boolean
(条件)并且愿意应用Predef.Boolean2boolean
转换的位置。如果您确实想执行以下操作,则可以手动执行此操作:
def parseMetrics(metric: Metric) = {
import scala.collection.JavaConverters._
metric.transactionMap.asScala.values.map(Predef.Boolean2boolean).map {
case false => "N"
case true => "Y"
}.toList
}
…但在我看来,至少Boolean
上的模式匹配比使用条件匹配要笨拙。
答案 1 :(得分:4)
使用if / else而不是match语句进行布尔检查:
def parseMetrics(metric: Metric) = {
import scala.collection.JavaConverters._
metric.transactionMap.asScala.values.map {
x => if (x) "Y" else "N"
}.toList
我怀疑在if语句中,java.lang.Boolean
(我猜为x
在这里)可以通过Boolean
强制为import scala.collection.JavaConverters._
...但是匹配语句不具有相同的强制性,但是必须显式地进行(或匹配java.lang.Boolean
值)。