5

Java ライブラリから関数を呼び出し、結果を処理し、CSV を吐き出す Scala プログラムに取り組んでいます。

問題の 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 は変換できないと推測しています。この質問を見ましたが、「明示的暗黙的変換」の書き方がわかりません。

4

4 に答える 4

9

編集推奨される方法は使用すること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変換または外側のマップを強制的に scalaMap.toMap変換し、内側のマップを強制的に scala ( immutable ) マップに変換します。不変部分は厳密には必要ありませんが、とにかく...

これは、この 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()
于 2013-06-11T16:12:00.103 に答える
2

「明示的暗黙的変換」の書き方がわかりません

もちろん、そのフレーズを使用する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))
于 2013-06-12T00:13:52.730 に答える
0

まず第一にMaps、scala にはミュータブルとイミュータブルの 2 つのバージョンとその他の主要なコレクションがあります。scala.collection.mutableデフォルトで使用されるのは不変バージョンであり、パッケージを介して可変バージョンにアクセスでき ます。

Java コレクションは可変であるため、Java コレクションをスカラ可変コレクションに変換することは、スカラ不変コレクションに変換するよりもはるかに簡単です。JavaConversionsJava コレクションを 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 immutableに変換しますscala.collection.mutable.Mapmutable Mapimmutable MapJavaConversionsjava.util.MapMap

于 2013-06-11T16:51:24.137 に答える
0

代わりに、私がこの目的のために特別に書いたscalaj-collectionライブラリを使用することもできます

import com.daodecode.scalaj.collection._

analysisAndCsvStuff(getData.deepAsScala)

それでおしまい。ネストされたすべての Java コレクションとプリミティブ型を scala バージョンに変換します。を使用して、不変のデータ構造に直接変換することもできますdeepAsScalaImmutable(もちろん、コピーのオーバーヘッドがいくらかあります)。

于 2016-01-29T00:47:53.393 に答える