【发布时间】:2011-07-10 11:53:24
【问题描述】:
我最近偶然发现了这个post,它为Scala 集合“引入”了collect 方法。用法很简单:
scala> val ints = List(1, "2", 3) collect { case i: Int => i }
ints: List[Int] = List(1, 3)
现在 maps 基本上是键值对的列表,在 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,Any] = Map(1 -> I, 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 或List,而不是Map[String, Int] 或List[Int]。
所以这是我的问题。
通过所有检查、转换和映射,我们成功地将Map[Any,Any] 转移到Map[String,Int]。有没有更好的方法来做到这一点?我的意思是类型在那里,JVM 只是看不到它们(就我而言)......
【问题讨论】:
标签: scala compiler-construction jvm scala-collections type-erasure