簡體   English   中英

如何轉換Java地圖以便在Scala中使用?

[英]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 JavaConversionsjava.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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM