Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I convert a Java map of maps for use in Scala?

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".

like image 337
Sam Daniel Avatar asked Jun 11 '13 15:06

Sam Daniel


1 Answers

Edit: the recommended way is to use JavaConverters and the .asScala method:

import scala.collection.JavaConverters._
val myScalaMap = myJavaMap.asScala.mapValues(_.asScala)

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:

import scala.collection.JavaConversions._
val myScalaMap = myJavaMap.mapValues(_.toMap)

.mapValues forces the conversion or the outer map to a scala Map 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:

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()
like image 74
gourlaysama Avatar answered Sep 19 '22 14:09

gourlaysama