Использование collect на картах в Scala
я недавно наткнулся на этот в должности, который "познакомит"collect
метод для коллекций Scala. Использование прямо вперед:
scala> val ints = List(1, "2", 3) collect { case i: Int => i }
ints: List[Int] = List(1, 3)
теперь карты - это в основном списки пар ключ-значение, которые представлены кортежами в 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, поэтому первое, что мы пытаемся использовать existential типы:
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)
to (Int,String)
мы фактически скопировали каждую пару и таким образом создали новую пару.
теперь вопрос. Как я уже упоминал, компилятор, конечно, жалуется...- Я сделал вид, что знаю, о чем говорю. Нет! Все, что я знаю, это то, что у Java не было дженериков с самого начала. В какой-то момент дженерики пришли на Java, но не в JVM. Таким образом, компилятор проверяет все типы, но как только код запущен, JVM не заботится о параметрическом типе. Он видит только, что это Map
или List
но не то, чтобы это Map[String, Int]
или List[Int]
.
так вот мой вопрос.
со всеми проверками, кастингом и отображением нам удалось передать Map[Any,Any]
to Map[String,Int]
. Есть ли лучший способ сделать это? Я имею в виду, что типы существуют, JVM просто не видит их (насколько это касается меня)...
1 ответов
pairs collect { case p @ (_: Int, _: String) => p.asInstanceOf[(Int, String)] }
или более кратким, но с некоторыми накладными расходами, я думаю
pairs collect { case (x: Int, y: String) => (x, y) }