kgx
kgx

Reputation: 1195

Efficient conversion of Scala Map[String,Seq[String]] to java.util.Map<String,List<String>>

I am new to Scala, trying to integrate some existing Java code with Scala-specific functionality in the Play Framework.

val scalaMap = getScalaMap() // returns Map[String,Seq[String]]

What is a nice clean way to convert scalaMap to use Java collections?

val javaMap = ???  //  java.util.Map<String,List<String>> 

It looks like I want to use JavaConversions, but I'm not sure how to chain together the nested collections. Thanks!

Upvotes: 3

Views: 939

Answers (2)

dhg
dhg

Reputation: 52681

Do not use mapValues. Use map:

import collection.JavaConverters._
val javaMap = scalaMap.map { case (k,v) => (k, v.asJava) }.asJava

Using mapValues will cause the inner-Map to be re-converted every time it is accessed.

A demonstration

A Scala Map

scala> val scalaMap = Map(1 -> Map('a -> "A"), 2 -> Map('b -> "B"))

Converting to a Java Map (but print something each time we convert the inner-Map)

scala> val javaMapBad = scalaMap.mapValues(v => { println("evaluating "+v); v.asJava }).asJava
evaluating Map('a -> A)
evaluating Map('b -> B)
javaMapBad: java.util.Map[Int,java.util.Map[Symbol,java.lang.String]] = {1={'a=A}, 2={'b=B}}

scala> javaMapBad.get(1)
evaluating Map('a -> A)     // Re-conversion!
res0: java.util.Map[Symbol,java.lang.String] = {'a=A}

scala> javaMapBad.get(1)
evaluating Map('a -> A)     // Re-conversion!
res1: java.util.Map[Symbol,java.lang.String] = {'a=A}

The right way to do it

scala> val javaMapGood = scalaMap.map{case (k,v) => {println("evaluating "+v); (k,v.asJava)}}.asJava
evaluating Map('a -> A)
evaluating Map('b -> B)
javaMapGood: java.util.Map[Int,java.util.Map[Symbol,java.lang.String]] = {1={'a=A}, 2={'b=B}}

scala> javaMapGood.get(1)  // no re-conversion
res6: java.util.Map[Symbol,java.lang.String] = {'a=A}

scala> javaMapGood.get(1)  // no re-conversion
res7: java.util.Map[Symbol,java.lang.String] = {'a=A}

Upvotes: 1

Tomasz Nurkiewicz
Tomasz Nurkiewicz

Reputation: 340733

Try this:

import collection.JavaConverters._
val javaMap = scalaMap.mapValues(_.asJava).asJava

It does the job in two steps:

  1. first converts Map[String,Seq[String]] to Map[String,java.util.List[String]]

  2. then the whole map to Java Map: java.util.Map[String,java.util.List[String]].

Upvotes: 4

Related Questions