我是Scala的新手,我们的项目将Java和Scala代码混合在一起(使用Play Framework)。我正在尝试编写一个可以采用嵌套Java Map的Scala方法,例如:
LinkedHashMap<String, LinkedHashMap<String, String>> groupingA = new LinkedHashMap<String, LinkedHashMap<String,String>>();
将Java对象传递给可以循环遍历的Scala函数。我有以下scala对象定义来尝试并支持上面的Java嵌套映射:
Seq[(String, Seq[(String,String)])]
Java文件和Scala文件都可以单独编译,但是当我的java对象尝试创建我的scala类的新实例并传入嵌套映射时,我收到编译器错误,其中包含以下详细信息:
[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中编写我们的游戏框架控制器。
答案 0 :(得分: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,迭代顺序将是同样的。)
我猜,你在处理查询参数吗?
答案 1 :(得分:1)
Seq
是Scala Collections层次结构中定义的基本特征。虽然java和scala提供字节码兼容性,但scala定义了许多自己的类型,包括它自己的集合库。这里的问题是如果你想编写惯用的scala,你需要将你的java数据转换为scala数据。我看到它的方式你有几个选择。
您可以使用Richard的解决方案,并在scala代码中将java类型转换为scala类型。我认为这很难看,因为它假设你的输入总是来自java土地。
您可以编写漂亮,完美的scala处理程序并提供一个提供丑陋的Java转换行为的伴随对象。这会将您的scala实现从java详细信息中解开。
或者你可以写一个隐含的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
}
}