1

我是 Scala 的新手,我们的项目将 Java 和 Scala 代码混合在一起(使用 Play 框架)。我正在尝试编写一个可以采用嵌套 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 编写我们的游戏框架控制器。

4

2 回答 2

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,迭代顺序将相同) .

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

于 2012-10-03T19:19:22.080 回答
1

Seq是在 Scala 集合层次结构中定义的基本特征。虽然 java 和 scala 提供字节码兼容性,但 scala 定义了许多自己的类型,包括自己的集合库。这里的问题是,如果你想编写惯用的 scala,你需要将你的 java 数据转换为 scala 数据。在我看来,你有几个选择。

  • 您可以使用 Richard 的解决方案并在您的 scala 代码中将 java 类型转换为 scala 类型。我认为这很难看,因为它假设您的输入将始终来自 java 领域。

  • 您可以编写漂亮、完美的 scala 处理程序,并提供一个提供丑陋 java 转换行为的伴生对象。这将您的 scala 实现与 java 细节分开。

  • 或者您可以编写一个隐式定义,如下面的定义,将其泛化到您的内心。

.

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
  }
}
于 2012-10-03T19:42:39.937 回答