如何转换地图的Java地图以在Scala中使用?

如何转换地图的Java地图以在Scala中使用?,java,scala,type-conversion,scala-java-interop,Java,Scala,Type Conversion,Scala Java Interop,我正在开发一个Scala程序,该程序从Java库调用函数,处理结果,并输出CSV 所讨论的Java函数如下所示: Map<String, Map<String, AtomicLong>> getData(); 错误: type mismatch; found:java.util.Map[java...String,java...Map[java...String,java...AtomicLong]] required: scala...

我正在开发一个Scala程序,该程序从Java库调用函数,处理结果,并输出CSV

所讨论的Java函数如下所示:

    Map<String, Map<String, AtomicLong>> getData();
错误:

    type mismatch;
    found:java.util.Map[java...String,java...Map[java...String,java...AtomicLong]]
    required: scala...Map[String,scala...Map[String,java...AtomicLong]]
(路径名破坏了格式。)


我猜java转换可以成功地转换外部java…映射,但不能转换内部java…映射。我看到了,但我不确定如何写“显-隐转换”

编辑:使用
JavaConverters
.asScala
方法:

import scala.collection.JavaConverters._
val myScalaMap = myJavaMap.asScala.mapValues(_.asScala)
请注意,您将从中获得可变映射。如果您想要不可变的,可以始终使用
.asScala.toMap


原始答案为
JavaConversions

简短的回答是:在外部映射上调用
.mapValues
,以转换内部映射:

import scala.collection.JavaConversions._
val myScalaMap = myJavaMap.mapValues(_.toMap)
.mapValues
强制将内部映射或外部映射转换为scala
map
.toMap
强制将内部映射转换为scala(不可变)映射。不可变的部分不是绝对必要的,但无论如何

这很类似于。简短示例:

scala> val a: java.util.Map[String, java.util.Map[String, String]] = new java.util.HashMap[String, java.util.Map[String, String]]
a: java.util.Map[String,java.util.Map[String,String]] = {}


scala> import scala.collection.JavaConversions._
import scala.collection.JavaConversions._

scala> val myScalaMap = a.mapValues(_.toMap)
myScalaMap: scala.collection.Map[String,scala.collection.immutable.Map[String,String]] = Map()

首先,scala中有两个版本的
Maps
和其他主要集合,可变和不可变。默认使用的是不可变版本,您可以通过
scala.collection.mutable
包访问可变版本

由于java集合的可变性,将java集合转换为scala可变集合比转换为scala不可变集合要容易得多
JavaConversions
无法将java集合转换为scala不可变集合

此外,
JavaCollections
无法将内部集合转换为scala类型

我建议您将java映射转换为scala数据结构,如下所示

val javaMap:java.util.HashMap[String,java.util.Map[String,Int]] = new java.util.HashMap()

val scalaMap:Map[String,Map[String,Int]] = javaMap.toMap.map { case (k,v) => k -> v.toMap}
scala.collection.mutable.Map
中定义了
.tomap
方法,该方法将
可变映射
转换为
不可变映射
。和
JavaConversions
java.util.Map
转换为scala immutable
Map

我不确定如何着手编写“显-隐转换”

当然,使用
JavaConverters
,这个短语暗示了一个自定义隐式

这里是来回的例子:

scala> import scala.collection.JavaConverters._
import scala.collection.JavaConverters._

scala> import java.util.concurrent.atomic.AtomicLong
import java.util.concurrent.atomic.AtomicLong

scala> val m = Map("a" -> Map("b" -> new AtomicLong(7L)))
m: scala.collection.immutable.Map[String,scala.collection.immutable.Map[String,java.util.concurrent.atomic.AtomicLong]] = Map(a -> Map(b -> 7))

scala> val j = m mapValues (_.asJava) asJava
warning: there were 1 feature warning(s); re-run with -feature for details
j: java.util.Map[String,java.util.Map[String,java.util.concurrent.atomic.AtomicLong]] = {a={b=7}}

scala> implicit class mapmap[A,B,C](val v:
     | java.util.Map[A,java.util.Map[B,C]]) extends AnyVal {
     | def asMapMap: Map[A,Map[B,C]] =
     | v.asScala.toMap.mapValues(_.asScala.toMap)
     | }
defined class mapmap

scala> j.asMapMap
res0: Map[String,Map[String,java.util.concurrent.atomic.AtomicLong]] = Map(a -> Map(b -> 7))
或者,您可以使用我专门为此编写的库

import com.daodecode.scalaj.collection._

analysisAndCsvStuff(getData.deepAsScala)

就这样。它将所有嵌套的java集合和基元类型转换为scala版本。您还可以使用
deepasscalaimummable
直接转换为不可变的数据结构(当然会有一些复制开销)

Huzzah!工作完美。感谢您快速简洁的回复@SamDaniel np:)。请看我的更新,尽管这两个版本都非常有效。我对人们强烈建议使用asScala的链接答案发表了评论。@som snytt谢谢,我对此不确定。令人惊讶的是,
JavaConversions
在2.11中没有被弃用。谢谢!Scala的“隐式”一开始对我来说就像伏都教,一个Scala n00b和一个受过ML类型系统艺术训练的人。但我很确定我现在明白它是怎么工作的了。
import com.daodecode.scalaj.collection._

analysisAndCsvStuff(getData.deepAsScala)