Подтвердить что ты не робот

Использование сбора на картах в Scala

Недавно я наткнулся на этот post, который "вводит" метод collect для коллекций Scala. Использование прямолинейно:

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 не заботится о параметрическом типе. Он видит только a Map или List, но не то, что он a Map[String, Int] или List[Int].

Итак, вот мой вопрос.

При проверке, кастинге и сопоставлении нам удалось передать Map[Any,Any] на Map[String,Int]. Есть ли лучший способ сделать это? Я имею в виду, что типы существуют, JVM просто не видит их (насколько мне известно)...

4b9b3361

Ответ 1

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

или более кратким, но с некоторыми накладными расходами, я думаю,

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