[英]How can I convert a Java map of maps for use in Scala?
我正在研究Scala程序,該程序從Java庫調用函數,處理結果並吐出CSV。
有問題的Java函數如下所示:
Map<String, Map<String, AtomicLong>> getData();
斯卡拉:
import scala.collection.JavaConversions._
def analysisAndCsvStuff(data: Map[String, Map[String, AtomicLong]]): Unit { ... }
錯誤:
type mismatch;
found:java.util.Map[java...String,java...Map[java...String,java...AtomicLong]]
required: scala...Map[String,scala...Map[String,java...AtomicLong]]
(路徑名稱破壞了格式。)
我猜測JavaConversions可以成功轉換外部java ... Map而不是內部java ... Map。 我看到了這個問題,但我不確定如何編寫“顯式隱式轉換”。
編輯 : 推薦的方法是使用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( 不可變 )地圖。 不可變部分並非絕對必要,但無論如何......
這與這個anwser非常相似。 簡短的例子:
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()
我不確定如何編寫“顯式隱式轉換”
當然,使用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))
首先,有兩個版本的Maps
和scala中的其他主要集合,可變和不可變。 默認使用是不可變版本,您可以通過scala.collection.mutable
包訪問可變版本。
由於Java Collections的可變性,將java Collections轉換為scala mutable Collections比轉換為scala immutable Collections要容易得多。 JavaConversions
無法將Java集合轉換為scala不可變集合。
此外, JavaCollections
無法將內部集合轉換為scala類型。
我建議你將java Map轉換為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}
.tomap
方法在scala.collection.mutable.Map
中定義,它將mutable Map
轉換為immutable Map
。 和JavaConversions
將java.util.Map
轉換為scala不可變Map
或者你可以使用我專門為此目的編寫的scalaj-collection庫
import com.daodecode.scalaj.collection._
analysisAndCsvStuff(getData.deepAsScala)
而已。 它會將所有嵌套的java集合和原始類型轉換為scala版本。 您還可以使用deepAsScalaImmutable
直接轉換為不可變數據結構(當然還有一些復制開銷)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.