I working on a Scala program that calls a function from a Java library, processes the results, and spits out a CSV.
The Java function in question looks like this:
Map<String, Map<String, AtomicLong>> getData();
The Scala:
import scala.collection.JavaConversions._
def analysisAndCsvStuff(data: Map[String, Map[String, AtomicLong]]): Unit { ... }
The error:
type mismatch;
found:java.util.Map[java...String,java...Map[java...String,java...AtomicLong]]
required: scala...Map[String,scala...Map[String,java...AtomicLong]]
(The path names were ruining the formatting.)
I'm guessing that the JavaConversions can successfully convert the outer java...Map but not the inner java...Map. I saw this question but I am unsure of how to go about writing an "explicit implicit conversion".
First of all, there are 2 versions of
Maps
and other major collections in scala, mutable and immutable. The default of use is immutable version, and you can access mutable version throughscala.collection.mutable
package.Because of the mutability of java Collections, converting java Collections to scala mutable Collections is pretty much easier than converting to scala immutable Collections.
JavaConversions
is unable to convert java Collections to scala immutable Collections.Furthermore,
JavaCollections
cannot convert your inner collections to scala types.I suggest you to convert your java Map as a scala data structure as follows.
The
.tomap
method is defined inscala.collection.mutable.Map
which convertsmutable Map
toimmutable Map
. andJavaConversions
convertsjava.util.Map
to scala immutableMap
Edit: the recommended way is to use
JavaConverters
and the.asScala
method:Note that you will get mutable maps out of this. You can always use
.asScala.toMap
if you want immutable ones.The original answer with
JavaConversions
:The short answer is: call
.mapValues
on the outer map to convert the inner map:.mapValues
forces the conversion or the outer map to a scalaMap
and.toMap
forces the conversion of the inner map to a scala (immutable) map. The immutable part isn't strictly necessary, but anyways...This is very similar to this anwser. Short example:
alternatively you can use scalaj-collection library i wrote specifically for this purpose
that's it. It will convert all nested java collections and primitive types to scala versions. You can also convert directly to immutable data structures using
deepAsScalaImmutable
(with some copying overhead of course)Using
JavaConverters
of course, that phrase suggests a custom implicit.Here is the back and forth: