50

I have a java map: java.util.Map<SomeObject, java.util.Collection<OtherObject>> and I would like to convert it to the scala map: Map[SomeObject, Set[OtherObject]]

I have used mapAsScalaMap but the result is not quite what I want, the result is: Map[SomeObject, java.util.Collection[OtherObject]]. How can I fix it to also convert the collection to a set?

NOTE: actually my original problem was to convert google's ArrayListMultimap<SomeObject, OtherObject> to a MultiMap[SomeObject, OtherObject] but since this was not possible I've split the problem. If you have a solution for the original problem, I'll also accept it as the answer.

om-nom-nom
  • 62,329
  • 13
  • 183
  • 228
  • look at this post: http://stackoverflow.com/questions/3127238/convert-java-util-mapstring-object-to-scala-collection-immutable-mapstring – Luther Blissett Jun 04 '13 at 13:32
  • and this page: http://www.scala-lang.org/docu/files/collections-api/collections_46.html – Luther Blissett Jun 04 '13 at 13:35
  • @LutherBlisset: It has the same result as mapAsScalaMap: Map[SomeObject, java.util.Collection[OtherObject]] –  Jun 04 '13 at 13:38
  • @LutherBlisset: Also, the docu page does not say anything about the conversion of nested types. I've tried to convert it to Map[SomeObject, Iterable[OtherObject]], since Collection is automatically converted to Iterable, but I get the same result as before. –  Jun 04 '13 at 13:44

4 Answers4

70

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

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

This has the advantage of not using magical implicit conversions but explicit calls to .asScala, while staying clean and consise.


The original answer with JavaConversions:

You can use scala.collection.JavaConversions to implicitly convert between Java and Scala:

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

Calling mapValues will trigger an implicit conversion from the java Map to a scala Map, and then calling toSet on the java collection with implicitly convert it to a scala collection and then to a Set.

By default, it returns a mutable Map, you can get an immutable one with an additional .toMap.

Short-ish example:

scala> val a: java.util.Map[String, java.util.Collection[String]] = new java.util.HashMap[String, java.util.Collection[String]]
a: java.util.Map[String,java.util.Collection[String]] = {}

scala> val b = new java.util.ArrayList[String]
b: java.util.ArrayList[String] = []

scala> b.add("hi")
res5: Boolean = true

scala> a.put("a", b)
res6: java.util.Collection[String] = []

scala> import scala.collection.JavaConversions._
import scala.collection.JavaConversions._

scala> val c = a.mapValues(_.toSet)
c: scala.collection.Map[String,scala.collection.immutable.Set[String]] = Map(a -> Set(hi))

scala> c.toMap
res7: scala.collection.immutable.Map[String,scala.collection.immutable.Set[String]] = Map(a -> Set(hi))
gourlaysama
  • 11,240
  • 3
  • 44
  • 51
  • Thank you, I was missing the "mapValues(_.toSet)" part –  Jun 04 '13 at 14:39
  • 2
    @Ha11owed People recommend converters: http://stackoverflow.com/questions/8301947/what-is-the-difference-between-javaconverters-and-javaconversions-in-scala and comments to http://docs.scala-lang.org/overviews/collections/conversions-between-java-and-scala-collections.html – som-snytt Jun 11 '13 at 23:37
5

Immutable Map myJavaMap.asScala.toMap

Mutable Map myJavaMap.asScala

Manali Bhosale
  • 261
  • 3
  • 3
2

If you have to do this from java:

List<Tuple2<A, B>> tuples = javaMap.entrySet().stream()
            .map(e -> Tuple2.apply(e.getKey(), e.getValue()))
            .collect(Collectors.toList());

scala.collection.Map scalaMap = scala.collection.Map$.MODULE$.apply(JavaConversions.asScalaBuffer(tuples).toSeq());

Based on: https://stackoverflow.com/a/45373345/5209935

Matthew
  • 10,361
  • 5
  • 42
  • 54
1

You can convert the Java Map into Scala Map using the below function:

val scalaMap = javaMap.asScala;

For using this you need to import the import scala.collection.JavaConverters._ library.

Hope this helps.

AJ.P
  • 406
  • 5
  • 8