6

假设我有一张地图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) 中的非变量类型参数 String 未选中,因为它已被擦除消除

我怎样才能摆脱警告?

4

3 回答 3

9

你可能想要:

val m1: Map[String, Int] = m collect {case (k:String, v:Int) => k->v}
于 2012-04-24T13:46:32.387 回答
3

(仅供参考。你想要的是virtualeyes的答案。)

val m1: Map[String, Int] = m flatMap { e =>
  e._1 match {
    case e1: String => Some(e1 -> e._2)
    case _ => None
  }
}
于 2012-04-24T13:46:48.577 回答
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 

`

于 2012-04-24T19:50:59.313 回答