13

Niedawno natknąłem się na to post, które "wprowadza" metodędla kolekcji Scala. Użycie jest proste:Używanie kolekcji na mapach w Scali

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

Teraz mapy są zasadniczo listy par klucz-wartość, które są reprezentowane przez krotki w Scala. Więc może chcesz spróbować czegoś takiego:

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 } 

Kompilator narzeka oczywiście ze względu na modelu wymazywania typu JVM, więc pierwszą rzeczą, którą staramy się przy użyciu typów egzystencjalne:

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

Chociaż kod przeszedł przez kompilator, a wynik jest "poprawny" (chcieliśmy par = = mamy pary), nadal nie dostaliśmy tego, co faktycznie chcieliśmy. Druga próba wygląda następująco:

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, jesteśmy prawie na miejscu:

scala> val realIntsToRealStrings = intsToStrings map { 
    | pair => (pair._1.asInstanceOf[Int], pair._2.asInstanceOf[String]) 
    | } 
realIntsToRealStrings: scala.collection.immutable.Map[Int,String] = Map(1 -> I) 

Zrobiliśmy to, ale zamiast odlewania tylko z (Any,Any) do (Int,String) faktycznie skopiowane każdej pary, a tym samym stworzył Nowa para.

Nadchodzi część z pytaniami. Jak wspomniałem "Kompilator narzeka oczywiście ..." Sprawiłem, że brzmiało to tak, jak naprawdę wiem o czym mówię. Ja nie! Wiem tylko, że Java nie miała od początku generycznych rodzajów. W pewnym momencie generics wszedł do Javy, ale nie do JVM. Tak więc kompilator sprawdza wszystkie typy, ale zaraz po uruchomieniu kodu JVM nie dba o typ parametryczny. Widzi tylko, że jest to Map lub List ale nie, że jest to Map[String, Int] lub List[Int].

Oto moje pytanie.

Po sprawdzeniu, przesłaniu i mapowaniu, udało nam się przesłać Map[Any,Any] do Map[String,Int]. Czy jest lepszy sposób na robienie tego? Znaczy typy są tam, JVM po prostu nie je zobaczyć (o ile jestem zaniepokojony) ...

Odpowiedz

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

lub bardziej zwięzły, ale z pewnym narzutem, myślę

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

super thx ! Wiedziałem, że Scala jest na tyle groźna, aby to się stało;) – agilesteel

+2

O, radość! Nowa specjalna postać (@), prawie to odgadłem. – Ciantic

Powiązane problemy