2012-10-03 104 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来使用,迭代顺序将是相同的)。

让我猜,你在处理查询参数吗?