Scala中的“未经检查的类型模式”警告?

时间:2012-04-24 13:30:51

标签: scala compiler-warnings type-erasure

假设我有一张地图m: Map[Any, Int]。现在,我只想从(String, Int)中获取m条目,并使用这些条目创建新地图m1: Map[String, Int]

我正在尝试执行以下操作:

val m1: Map[String, Int] = m collect {case e:(String, Int) => e}

它似乎有效但我得到一个警告:非变量类型参数类型模式(String,Int)中的字符串未选中,因为它被删除删除。

如何摆脱警告?

3 个答案:

答案 0 :(得分:9)

你可能想要:

val m1: Map[String, Int] = m collect {case (k:String, v:Int) => k->v}

答案 1 :(得分:3)

(仅供参考。你想要的是virtualeyes’s answer。)

val m1: Map[String, Int] = m flatMap { e =>
  e._1 match {
    case e1: String => Some(e1 -> e._2)
    case _ => None
  }
}

答案 2 :(得分:2)

仔细测试将显示您的解决方案实际上匹配地图中的所有内容,而不仅仅是类型(String,Int)的条目。来自编译器的警告告诉您,匹配的类型将在运行时丢弃,因此您的代码实际上是这样做的:

val m1: Map[String, Int] = m collect {case e:Tuple2[Any,Any] => e.asInstanceOf[Tuple2[String,Int]]}

并且asInstanceOf调用不会爆炸,因为它只会转换为Tuple2并且(String,Int)位因擦除而再次丢失。当你尝试迭代结果时,你会得到一个令人讨厌的失败......

在REPL中尝试此操作

  val m:Map[String,Int] = Map("2" -> 3, 3 -> 4, "6" -> 10) collect {case e:(String, Int) => e}
  // Oops, thought we would get '2'
  m size 
  // Nothing wrong with this code except m contains some
  // hidden nasties which causes us to blow up
  for ((s:String, i:Int) <- m) yield s.length + i 

`