我最近偶然在這個post,其中「介紹」爲Scala集合的collect
方法。用法是直截了當:使用收集的地圖,斯卡拉
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的類型擦除模式,所以我們嘗試的第一件事就是使用存在類型:
scala> val intsToStrings = pairs collect { case pair: (_, _) => pair }
intsToString: scala.collection.immutable.Map[Any,Any] = Map(1 -> I, II -> 2)
雖然代碼通過了編譯器,結果是「正確的」(我們希望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)
好了,我們幾乎沒有:
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只是沒有看到他們(據我所關注的)...
酷THX !我知道Scala是足夠真棒做到這一點;) – agilesteel
哦喜悅!新的特殊字符(@),我幾乎猜到了。 – Ciantic