St.Antario
St.Antario

Reputation: 27425

Converting Map[String, Double] to java.util.Map[String, java.lang.Double]

I thought we can rely on implicit conversion which converts scala.Double to java.lang.Double. So I tried the following:

import scala.collection.JavaConverters._

object Main extends App {
  def main(args: Array[String]) = {
    val m = Map("10" -> 20.0)
    doSome(m.asJava) //error. Type mismatch found: java.util.Map[String,scala.Double]
                     //                  required: java.util.Map[String,java.lang.Double]
    doSome2(m.asJava)
  }
  def doSome(m: java.util.Map[java.lang.String, java.lang.Double]) = println(m)
  def doSome2(m: java.util.Map[java.lang.String, Double]) = println(m)
}

Why doesn't it work? What would be the idiomatic way to perform such a conversion?

Upvotes: 3

Views: 1892

Answers (3)

Alvaro Carrasco
Alvaro Carrasco

Reputation: 6182

You need the boxed version of double:

import scala.collection.JavaConverters._

m.mapValues(Double.box).asJava

The implicits are able to convert a value of Double to java.lang.Double, but not a Map[String,Double] to java.util.Map[String,java.lang.Double].

String requires no conversion because String is a java.lang.String while Double is a double (primitive).

Upvotes: 6

Max
Max

Reputation: 661

It seems that for String, you don't need to do any conversion, but is not the case for Double. You can use the method double2Double which is defined in Predef to convert to java.double.

import scala.collection.JavaConverters._

m.map { case (k, v) => k -> double2Double(v) }.asJava

or another way is to do asInstanceOf to convert it to Java map directly.

Upvotes: 3

radumanolescu
radumanolescu

Reputation: 4161

The issue here is that scala.Double is a primitive (equivalent to Java double) while java.lang.Double is a class. They are not at all the same thing. The JavaConverters converts between Java Map and Scala Map, not their contents. This works:

import scala.collection.JavaConverters._

object Main {

  def main(args: Array[String]): Unit = {
    val m = Map("10" -> 20.0)
    doSome(mapConv(m))
    doSome2(m.asJava)
  }
  def doSome(m: java.util.Map[java.lang.String, java.lang.Double]) = println(m)
  def doSome2(m: java.util.Map[java.lang.String, Double]) = println(m)

  def mapConv(msd: Map[String, Double]): java.util.Map[java.lang.String, java.lang.Double] = {
    msd.map { case (k, v) => (k -> new java.lang.Double(v)) }.asJava
  }
}

Upvotes: 2

Related Questions