A Java API returns a java.util.Map<java.lang.String,java.lang.Boolean>
;. I would like to put that into a Map[String,Boolean]
So imagine we have:
var scalaMap : Map[String,Boolean] = Map.empty
val javaMap = new JavaClass().map() // Returns java.util.Map<java.lang.String,java.lang.Boolean>
You can't do Map.empty ++ javaMap
, because the ++ method does not know about Java maps. I tried:
scalaMap = Map.empty ++ new collection.jcl.MapWrapper[String,Boolean] {
override def underlying = javaMap
}
and:
scalaMap = Map.empty ++ new collection.jcl.MapWrapper[java.lang.String,java.lang.Boolean] {
override def underlying = javaMap
}
These both fail to compile, because of the generics - java.lang.String
is not the same as a scala String.
Is there a good way of doing this, short of copying the map manually?
EDIT: Thanks, all good answers, I learned a lot from all of them. However, I made a mistake by posting a simpler problem here than the one I actually have. So, if you allow me, I'll generalise the question - What the API actually returns is
java.util.Map<java.lang.String, java.util.Map<SomeJavaEnum,java.lang.String>>
And I need to move this to Map[String, Map[SomeJavaEnum,String]]
It probably does not seem like too much of a complication, but it adds an extra level of type erasure, and the only way I found of moving this to a Scala map was deep-copying it (using some of the techniques you suggested below). Anyone any hints? I kind of solved my problem by defining an implicit conversion for my exact types, so at least the ugliness is hidden in its own trait, but still feels a bit clumsy deep copying the lot.
A Scala
String
is ajava.lang.String
but a ScalaBoolean
is not ajava.lang.Boolean
. Hence the following works:But your problem is still the issue with the
Boolean
difference. You'll have to "fold" the Java map into the scala one: try again using the ScalaBoolean
type:Then
mm
is a scala map containing the contents of the original scala map plus what was in the Java mapAt least with Scala 2.9.2 there's an easier way with the collections conversions: import "import collection.JavaConversions._" and use "toMap".
Example:
It works fine with a java.util.map of String to Boolean.
useJavaMap.scala
test/test.java
Commandline
I think I have a partial answer...
If you convert the java map to a scala map with the java types. You can then map it to a scala map of scala types:
The flaw in this plan is that the type of
scalaMap
is Iterable[(java.lang.String, Boolean)] not a map. I feel so close, can someone cleverer than me fix the last statement to make this work?!