微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在Scala的地图上使用收集

我最近偶然发现了这个 post,它引进了Scala系列的收集方法.用法很直接:

scala> val ints = List(1,"2",3) collect { case i: Int => i }
ints: List[Int] = List(1,3)

现在地图基本上是Scala中的元组表示的键值对的列表.所以你可能想尝试这样的东西:

scala> val pairs = Map(1 -> "I","II" -> 2)
pairs: scala.collection.immutable.Map[Any,Any] = Map(1 -> I,II -> 2)

scala> val intsToStrings = pairs collect { case pair: (Int,String) => pair }

编译器抱怨当然是由于JVM的类型擦除模型,所以我们首先尝试的是使用存在类型:

scala> val intsToStrings = pairs collect { case pair: (_,_) => pair }
intsToString: scala.collection.immutable.Map[Any,II -> 2)

虽然代码通过了编译器,结果是“正确的”(我们希望对=>我们有对),但我们仍然没有得到我们实际想要的.第二次尝试如下所示:

scala> val intsToStrings = pairs collect {
     |    case pair: (_,_) if pair._1.isinstanceOf[Int] && pair._2.isinstanceOf[String] => pair
     | }
intsToStrings: scala.collection.immutable.Map[Any,Any] = Map(1 -> I)

好的,我们差不多了

scala> val realIntsToRealStrings = intsToStrings map {
     |    pair => (pair._1.asInstanceOf[Int],pair._2.asInstanceOf[String])
     | }
realIntsToRealStrings: scala.collection.immutable.Map[Int,String] = Map(1 -> I)

我们做到了,但是不是只从(Any,Any)转换为(Int,String),我们实际上复制了每一对,从而创建了一个新的对.

现在是问题的一部分.正如我提到的“编译器当然抱怨…”我听起来像我真的知道我在说什么.我不!我所知道的是,Java从一开始就没有泛型.在某种程度上,仿制药进入Java而不是进入JVM.所以编译器检查所​​有的类型,但一旦代码运行,JVM就不关心参数类型.它只看到它是一个地图或列表,但不是它是一个Map [String,Int]或List [Int].

所以这是我的问题.

通过所有的检查,投射和映射,我们设法将Map [A​​ny,Any]映射到Map [String,Int].有更好的方法吗?我的意思是类型在那里,JVM只是看不到他们(就我而言)…

解决方法

pairs collect { case p @ (_: Int,_: String) => p.asInstanceOf[(Int,String)] }

或者更简洁,但有一些开销,我想

pairs collect { case (x: Int,y: String) => (x,y) }

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐