2009-06-22 12 views
14

Một API Java trả lại một java.util.Map<java.lang.String,java.lang.Boolean> ;. Tôi muốn đặt đó vào một Map[String,Boolean]Cách chuyển đổi từ từ java.util.Map sang một Bản đồ Scala

Hãy tưởng tượng chúng ta có:

var scalaMap : Map[String,Boolean] = Map.empty 
val javaMap = new JavaClass().map() // Returns java.util.Map<java.lang.String,java.lang.Boolean> 

Bạn không thể làm Map.empty ++ javaMap, bởi vì phương pháp ++ không biết về bản đồ Java. Tôi cố gắng:

scalaMap = Map.empty ++ new collection.jcl.MapWrapper[String,Boolean] { 
    override def underlying = javaMap 
} 

và:

scalaMap = Map.empty ++ new collection.jcl.MapWrapper[java.lang.String,java.lang.Boolean] { 
    override def underlying = javaMap 
    } 

Những cả thất bại trong việc biên dịch, vì Generics - java.lang.String là không giống như một String scala.

Có cách nào tốt để thực hiện việc này, không thể sao chép bản đồ theo cách thủ công?

EDIT: Cảm ơn, tất cả các câu trả lời hay, tôi đã học được rất nhiều từ tất cả chúng. Tuy nhiên, tôi đã thực hiện một sai lầm bằng cách đăng một vấn đề đơn giản ở đây hơn là một trong những tôi thực sự có. Vì vậy, nếu bạn cho phép tôi, tôi sẽ khái quát những câu hỏi - Có gì API thực sự trở lại là

java.util.Map<java.lang.String, java.util.Map<SomeJavaEnum,java.lang.String>> 

Và tôi cần phải di chuyển này vào Map [String, Bản đồ [SomeJavaEnum, String]]

Nó có lẽ dường như không quá phức tạp, nhưng nó làm tăng thêm cấp độ xóa, và cách duy nhất tôi tìm thấy là di chuyển nó sang bản đồ Scala đã sao chép sâu nó (sử dụng một số kỹ thuật mà bạn gợi ý dưới đây). Bất cứ ai gợi ý? Tôi đã giải quyết được vấn đề của mình bằng cách xác định một chuyển đổi tiềm ẩn cho các loại chính xác của tôi, vì vậy ít nhất sự xấu xa bị ẩn đi trong đặc điểm riêng của nó, nhưng vẫn cảm thấy hơi bối rối khi sao chép rất nhiều.

+0

Tôi rất thích câu trả lời Chuyển đổi tôi nhận được từ nhóm người dùng scala. Chỉ cần kiểm tra xem nó có hoạt động không ... Nhưng giờ đã quá muộn rồi, vì vậy sẽ sớm đăng lại ... – George

Trả lời

2

useJavaMap.scala

import test._ 
import java.lang.Boolean 
import java.util.{Map => JavaMap} 
import collection.jcl.MapWrapper 

object useJavaMap { 
    def main(args: Array[String]) { 
    var scalaMap : Map[String, Boolean] = Map.empty 
    scalaMap = toMap(test.testing()) 
    println(scalaMap) 
    } 

    def toMap[K, E](m: JavaMap[K, E]): Map[K, E] = { 
    Map.empty ++ new MapWrapper[K, E]() { 
     def underlying = m 
    } 
    } 
} 

thử nghiệm/test.java

package test; 

import java.util.*; 

public class test { 
    public static Map<String, Boolean> testing() { 
     Map<String, Boolean> x = new HashMap<String, Boolean>(); 
     x.put("Test",Boolean.FALSE); 
     return x; 
    } 
    private test() {} 
} 

dòng lệnh

javac test\test.java 
scalac useJavaMap.scala 
scala useJavaMap 
> Map(Test -> false) 
+0

Không phải những công trình này, tôi sợ. Đây là các lớp được generic hóa - Bản đồ [String, Boolean] không giống với Bản đồ [java.lang.String, java.lang.Boolean], vì vậy bạn nhận được: loại không phù hợp; tìm thấy: java.lang.Object với scala.collection.jcl.MapWrapper [String, Boolean] \t {...} bắt buộc: Bản đồ [String, Boolean] (sử dụng ví dụ đầu tiên) – George

+0

có thời gian để dùng thử. đầy đủ mẫu cung cấp – jitter

+0

Cảm ơn bạn, 'Map.empty ++ JMapWrapper [K, V] (myJavaMap)' là những gì tôi muốn! –

0

Tôi nghĩ rằng tôi có một câu trả lời một phần ...

Nếu bạn chuyển bản đồ java thành bản đồ scala với các loại java. Sau đó bạn có thể ánh xạ nó vào một bản đồ scala các loại scala:

val javaMap = new java.util.TreeMap[java.lang.String, java.lang.Boolean] 
val temp = new collection.jcl.MapWrapper[java.lang.String,java.lang.Boolean] { 
    override def underlying = javaMap 
} 
val scalaMap = temp.map{ 
    case (k, v) => (k.asInstanceOf[String] -> v.asInstanceOf[Boolean]) 
} 

Các lỗ hổng trong kế hoạch này là các loại scalaMap là Iterable [(java.lang.String, Boolean)] không phải là một bản đồ. Tôi cảm thấy rất gần, ai đó có thể thông minh hơn tôi để sửa lời tuyên bố cuối cùng để thực hiện công việc này ?!

6

Một Scala String là một java.lang.Stringnhưng một Scala Booleankhông phải là một java.lang.Boolean.Do đó các công việc sau:

import collection.jcl.Conversions._ 
import collection.mutable.{Map => MMap} 
import java.util.Collections._ 
import java.util.{Map => JMap} 

val jm: JMap[String, java.lang.Boolean] = singletonMap("HELLO", java.lang.Boolean.TRUE) 

val sm: MMap[String, java.lang.Boolean] = jm //COMPILES FINE 

Nhưng vấn đề của bạn vẫn là vấn đề với chênh lệch Boolean. Bạn sẽ phải "gấp" bản đồ Java vào scala một: thử lại bằng cách sử dụng loại Scala Boolean:

val sm: MMap[String, Boolean] = collection.mutable.Map.empty + ("WORLD" -> false) 
val mm = (sm /: jm) { (s, t2) => s + (t2._1 -> t2._2.booleanValue) } 

Sau đó mm là một bản đồ scala chứa các nội dung của bản đồ gốc scala cộng với những gì đang ở trong Bản đồ Java

+0

Trên thực tế, câu trả lời của bạn chuyển thành bản đồ có thể thay đổi, trong khi tác giả yêu cầu không thay đổi. –

11

Ít nhất với Scala 2.9.2, có một cách dễ dàng hơn với chuyển đổi bộ sưu tập: nhập "collection import.JavaConversions._" và sử dụng "toMap".

Ví dụ:

// show with Java Map: 

scala> import java.util.{Map=>JMap} 
scala> val jenv: JMap[String,String] = System.getenv() 
jenv: java.util.Map[String,String] = {TERM=xterm, ANT_OPTS=-Xmx512m ...} 

scala> jenv.keySet() 
res1: java.util.Set[String] = [TERM, ANT_OPTS...] 

// Now with Scala Map: 

scala> import collection.JavaConversions._ 
scala> val env: Map[String,String] = System.getenv.toMap // <--- TADA <--- 
env: Map[String,String] = Map(ANT_OPTS -> -Xmx512m, TERM -> xterm ...) 

// Just to prove it's got Scala functionality: 

scala> env.filterKeys(_.indexOf("TERM")>=0) 
res6: scala.collection.immutable.Map[String,String] = Map(TERM -> xterm, 
    TERM_PROGRAM -> iTerm.app, ITERM_PROFILE -> Default) 

Nó hoạt động tốt với một java.util.map của String để Boolean.