在 Scala 中的地图上使用收集

问题描述 投票:0回答:1

我最近偶然发现了这篇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 jvm scala-collections type-erasure
1个回答
23
投票
pairs collect { case p @ (_: Int, _: String) => p.asInstanceOf[(Int, String)] }

或更简洁,但有一些开销,我认为

pairs collect { case (x: Int, y: String) => (x, y) }
© www.soinside.com 2019 - 2024. All rights reserved.