2012-10-03 61 views
1

我是Scala的新手,我們的項目將Java和Scala代碼混合在一起(使用Play框架)。我試圖寫一個Scala的方法,可以採取一個嵌套的Java地圖,如:Java嵌套映射到Scala嵌套序列

LinkedHashMap<String, LinkedHashMap<String, String>> groupingA = new LinkedHashMap<String, LinkedHashMap<String,String>>(); 

,並已通過一個Scala的功能,可以通過它循環,Java對象。我有以下斯卡拉對象的定義,試圖支持上述Java的嵌套圖:

Seq[(String, Seq[(String,String)])] 

兩個Java文件和Scala文件編譯罰款分別,但是當我的java對象嘗試創建我的斯卡拉的新實例類,並通過在嵌套地圖,我得到一個編譯錯誤有以下細節:這裏

[error] ..... overloaded method value apply with alternatives: 
[error] (options: java.util.List[String])scala.collection.mutable.Buffer[(String, String)] <and> 
[error] (options: scala.collection.immutable.List[String])List[(String, String)] <and> 
[error] (options: java.util.Map[String,String])Seq[(String, String)] <and> 
[error] (options: scala.collection.immutable.Map[String,String])Seq[(String, String)] <and> 
[error] (options: (String, String)*)Seq[(String, String)] 
[error] cannot be applied to (java.util.LinkedHashMap[java.lang.String,java.util.LinkedHashMap[java.lang.String,java.lang.String]]) 

任何想法我如何能在一個嵌套的Java的LinkedHashMap通過諸如以上到Scala的文件在那裏我可以統稱迭代在嵌套集合?我試圖編寫這個通用的腳本,以至於它也適用於嵌套的Scala集合,以防我們改用Scala而不是Java來編寫我們的框架控制器。

+1

「但是當我的java對象試圖創建我的斯卡拉類的新實例,並通過在嵌套圖」 - 請向我們提供德codez :) – fresskoma

+0

是'LinkedHashMap'一個'Seq'?我認爲這隻適用於斯卡拉集合層次結構的成員。編譯時間或運行時錯誤。我會認爲這將是一個編譯錯誤,因爲他們的類型不對齊。 – nsfyn55

回答

1

Seq是在Scala Collections層次結構中定義的基本特徵。雖然java和scala提供了字節碼兼容性,但scala定義了許多自己的類型,包括它自己的集合庫。這裏蹭的是如果你想編寫慣用的scala你需要將你的java數據轉換爲scala數據。我看到它的方式有幾種選擇。

  • 您可以使用Richard的解決方案並將java類型轉換爲您的scala代碼中的scala類型。我認爲這很醜陋,因爲它假定你的輸入將始終來自java land。

  • 您可以編寫美觀,完美的scala處理程序,並提供一個伴隨對象,它提供醜陋的java轉換行爲。這從java細節中解開了你的scala實現。

  • 或者你可以寫一個隱式的def,就像下面的一個將其泛化到你的內容中一樣。

import java.util.LinkedHashMap 
import scala.collection.JavaConversions.mapAsScalaMap 

object App{ 
    implicit def wrapLhm[K,V,G](i:LinkedHashMap[K,LinkedHashMap[G,V]]):LHMWrapper[K,V,G] = new LHMWrapper[K,V,G](i) 

    def main(args: Array[String]){ 
    println("Hello World!") 
    val lhm = new LinkedHashMap[String, LinkedHashMap[String,String]]() 
    val inner = new LinkedHashMap[String,String]() 
    inner.put("one", "one") 
    lhm.put("outer",inner); 
    val s = lhm.getSeq() 
    println(s.toString()) 
    } 
    class LHMWrapper[K,V,G](value: LinkedHashMap[K,LinkedHashMap[G,V]]){ 
    def getSeq():Seq[ (K, Seq[(G,V)])] = mapAsScalaMap(value).mapValues(mapAsScalaMap(_).toSeq).toSeq 
    } 
} 
+0

感謝您的提示。我在提出這個問題後不久就意識到,在我的代碼(玩框架)中,他們正在調用一些幫助我將java數據轉換爲scala數據的幫助器。這是我的困惑來自哪裏,因爲我不知道有一個幫手 - 它似乎只是魔術。沒有爲我正在尋找的轉換類型定義幫手。我選擇你的答案是正確的,因爲你應該寫一個可以處理java或scala支持的數據的scala代碼。 – rmmeans

1

試試這個:

import scala.collections.JavaConversions.mapAsScalaMap 

val lhm: LinkedHashMap[String, LinkedHashMap[String, String]] = getLHM() 
val scalaMap = mapAsScalaMap(lhm).mapValues(mapAsScalaMap(_).toSeq).toSeq 

我進行了測試,得到了型Seq[String, Seq[(String, String)]]

的結果(轉換將包裝原始的Java對象,而不是實際上的副本創建Scala的對象因此轉換到Seq並不是必須的,你可以把它作爲一個Map來使用,迭代順序將是相同的)。

讓我猜,你在處理查詢參數嗎?