2009-06-22 34 views
14

Java API返回java.util.Map<java.lang.String,java.lang.Boolean>;。我想它放入一個Map[String,Boolean]如何轉換爲java.util.Map到斯卡拉地圖

所以,想象一下,我們有:

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

你不能這麼做Map.empty ++ javaMap,因爲++方法不知道有關Java的地圖。我想:

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

和:

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

這些都無法編譯,因爲仿製藥的, - java.lang.String是不一樣的Scala的字符串。

有沒有這樣做的好方法,手動複製地圖短?

編輯:謝謝,所有好的答案,我從他們中學到了很多。然而,我在這裏發佈了一個比我實際擁有的更簡單的問題而犯了一個錯誤。所以,如果你讓我,我會概括問題 - 什麼是API實際上返回是

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

我需要移動這地圖[字符串,地圖[SomeJavaEnum,字符串]]

它可能看起來不太複雜,但它增加了一個額外的類型擦除級別,我發現將它移到Scala地圖的唯一方式是深度複製它(使用您在下面建議的一些技巧)。任何提示?我通過爲我的確切類型定義一個隱式轉換來解決我的問題,所以至少這個醜陋隱藏在它自己的特質中,但仍然感覺有點笨拙。

+0

我很喜歡我從scala用戶組獲得的轉換答案。只需要檢查它是否可行...但現在這裏太晚了,所以很快會回來... – George 2009-06-22 22:30:57

回答

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 
    } 
    } 
} 

測試/ 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() {} 
} 

命令行

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

恐怕這些作品都沒有。這些是通用類 - Map [String,Boolean]與Map [java.lang.String,java.lang.Boolean]不一樣,所以你得到:type mismatch;找到:java.lang.Object with scala.collection.jcl.MapWrapper [String,Boolean] \t {...}必需:Map [String,Boolean](使用第一個示例) – George 2009-06-22 16:36:25

+0

有時間嘗試它。提供全部示例 – jitter 2009-06-22 17:37:51

+0

謝謝'Map.empty ++ JMapWrapper [K,V](myJavaMap)'是我想要的! – 2011-05-01 05:35:59

0

我想我有一個部分的答案...

如果您將java映射轉換爲java類型的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]) 
} 

在這個計劃中的缺陷是,scalaMap類型是可迭代[(java.lang.String中,布爾值)]不是地圖。我感到如此接近,能否有人比我更聰明地修正最後的聲明來使這項工作?!

6

斯卡拉Stringjava.lang.String斯卡拉Boolean不是一個java.lang.Boolean。因此,以下工作:

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 

但你的問題仍然是與Boolean差異的問題。你必須「摺疊」在Java映射到一個階:

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

然後mm被包含原始斯卡拉地圖的內容以及什麼是在斯卡拉地圖:使用Scala的Boolean型再試一次Java地圖

+0

其實,你的答案轉換爲可變映射,而作者要求不可變。 – 2011-05-01 04:35:13

11

至少在Scala 2.9.2中,集合轉換有一個更簡單的方法:import「import collection.JavaConversions._」並使用「toMap」。

例子:

// 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) 

它正常工作與字符串的布爾一個java.util.map。