0

I am trying to convert a java.util.Map to a Map[String, Any]. I get the java map as part of my java interface.

I am running into problems with conversions of Integer to Int and java.lang.Long to scala.Long.

code is as follows:

import java.math.{BigDecimal => JavaBigDecimal}
import scala.collection.JavaConverters.mapAsScalaMapConverter
import scala.collection.mutable

val input = new java.util.HashMap[String, Object]()
input.put("test", Integer.valueOf(1))
input.put("test2", new JavaBigDecimal("12"))

val scalaMap = input.asScala
//noinspection ScalaStyle
val filter: mutable.Map[String, Object] = scalaMap.filter(_._2 != null)
val toMap: Map[String, Any] = filter.toMap
val initialContext = toMap.mapValues {
  case b: JavaBigDecimal => BigDecimal(b)
  case i: Integer => Integer2int(i)
  case l: java.lang.Long => l.toLong
  case a: Any if a == null => None
  case a: Any if a != null => a
}

initialContext.get("test").get.getClass
initialContext.get("test2").get.getClass

The result of the last 2 lines is:

res3: Class[?0] = class java.lang.Integer
res4: Class[?0] = class scala.math.BigDecimal

The BigDecimal does what I expect it to do, but Int (and also Long), do not. It seems to get magically converted back into Integer. Also when I just add a different static number:

case i: Integer => 42

it will turn this into an Integer

I need this Class information though, because deeper into my java API I do a check if the expected type matches the gotten type and Int (expected) does not match Integer.

3
  • After some experimenting it looks like it will always output an Integer in the getClass, even when starting with a scala Map filled with Int and something else (so type Any). Commented Dec 31, 2015 at 13:06
  • Int is just an alias to Integer, and so on, there is no wrappers or conversions -- this are very same classes. The same goes for other primitives. Commented Dec 31, 2015 at 13:30
  • @om-nom-nom No, they certainly aren't. classOf[Int] == classOf[Integer] will return false, same for typeOf. In some cases Int erases to Integer at runtime, but not always. Commented Dec 31, 2015 at 21:39

1 Answer 1

3

The partial function

{
  case b: JavaBigDecimal => BigDecimal(b)
  case i: Integer => Integer2int(i)
  case l: java.lang.Long => l.toLong
  case a: Any if a == null => None
  case a: Any if a != null => a
}

returns Any. But this type actually doesn't exist on the JVM; instead the Scala compiler uses Object. So primitive types are autoboxed: Int to java.lang.Integer, Long to java.lang.Long, etc.

I need this Class information though, because deeper into my java API I do a check if the expected type matches the gotten type and Int (expected) does not match Integer.

Either use the boxed types for comparison, or store the desired class alongside the value in a Map[String, (Any, Class[_])].

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the clarification. I also figured it works "properly" and I just needed to expend my check, instad of just comparing Class[Int] I also need to check if it might not be Integer as well (or Long if that is the case, etc). A bit annoying, but I guess there is no other way around it

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.