13

Gần đây, tôi đã tình cờ đọc qua số này post, trong đó "giới thiệu" phương thức collect cho bộ sưu tập Scala. Việc sử dụng là thẳng về phía trước:Sử dụng thu thập trên bản đồ tại Scala

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

Bây giờ bản đồ cơ bản danh sách các cặp khóa-giá trị, được đại diện bởi các tuple trong Scala. Vì vậy, bạn có thể muốn thử một cái gì đó như thế này:

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 } 

Trình biên dịch phàn nàn tất nhiên do mô hình tẩy xoá loại JVM, do đó, điều đầu tiên chúng tôi cố gắng được sử dụng các loại hiện sinh:

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

Mặc dù mã thông qua trình biên dịch, và kết quả là "đúng" (chúng tôi muốn cặp => chúng tôi có cặp) chúng tôi vẫn không nhận được những gì chúng tôi thực sự muốn. Nỗ lực thứ hai trông như thế này:

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, chúng ta đang ở gần đó:

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

Chúng tôi đã làm điều đó, nhưng thay vì chỉ đúc (Any,Any)-(Int,String) chúng tôi thực sự sao chép mỗi cặp và do đó tạo ra một cặp mới.

Bây giờ đến phần câu hỏi. Như tôi đã đề cập "Trình biên dịch phàn nàn tất nhiên ..." Tôi làm cho nó nghe như tôi thực sự biết những gì tôi đang nói về. Tôi không! Tất cả những gì tôi biết là Java không có Generics ngay từ đầu. Tại một số điểm generics đến Java nhưng không vào JVM. Vì vậy trình biên dịch kiểm tra tất cả các kiểu, nhưng ngay sau khi mã đang chạy, JVM không quan tâm đến kiểu tham số. Nó chỉ thấy rằng đó là một số Map hoặc List nhưng không phải là nó là Map[String, Int] hoặc List[Int].

Vì vậy, đây là câu hỏi của tôi.

Với tất cả việc kiểm tra, truyền và lập bản đồ, chúng tôi đã quản lý để chuyển một số Map[Any,Any] đến Map[String,Int]. Có cách nào tốt hơn để làm điều đó không? Ý tôi là các loại đang có, JVM chỉ không nhìn thấy chúng (như xa như tôi có liên quan) ...

Trả lời

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

hoặc ngắn gọn hơn, nhưng với một số chi phí, tôi nghĩ

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

mát thx ! Tôi biết Scala là tuyệt vời, đủ để làm cho nó xảy ra;) – agilesteel

+2

Oh niềm vui! Nhân vật đặc biệt mới (@), tôi gần như đoán được. – Ciantic

Các vấn đề liên quan