13

最近、Scalaコレクションのcollectメソッドを紹介するpostを見つけました。使い方は簡単です:Scalaでのコレクションの使用

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

マップは基本的にScalaではタプルで表現されているキーと値のペアのリストです。

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

ものの:私たちがしようと最初にすることは実存のタイプを使用しているので、原因JVMの型消去モデルに

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 } 

コンパイラはもちろん文句:だから、このような何かを試してみたいことがありますコードはコンパイラに渡され、結果は「正しい」(ペアが欲しかった=>我々はペアを持っていた)、我々はまだ実際には望んでいなかった。第二の試みは次のようになります。

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) 

[OK]を、私たちはほとんどあります

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はちょうど...(私に関する限り)

答えて

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

またはより簡潔に、それらを見ていないが、いくつかのオーバーヘッドで、私は

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

クールTHXを考えます!私はScalaがそれを実現するのに十分素晴らしいことを知っていた;) – agilesteel

+2

ああ喜び!新しい特殊文字(@)、私はほとんどそれを推測しました。 – Ciantic

関連する問題