8

I find lots of people trying to do this, and asking about this but the question is always answered in terms of scala code. I need to call an API that is expecting a scala.collection.immutable.Map but I have a java.util.Map, how can I cleanly convert from the latter to the former in my java code? The compiler disagrees with the sentiment that it is an implicit conversion as it barfs on that when I try it!

Thank you!

NSA
  • 5,689
  • 8
  • 37
  • 48

1 Answers1

15

Getting an immutable Scala map is a little tricky because the conversions provided by the collections library return all return mutable ones, and you can't just use toMap because it needs an implicit argument that the Java compiler of course won't provide. A complete solution with that implicit argument looks like this:

import scala.collection.JavaConverters$;
import scala.collection.immutable.Map;

public class Whatever {
  public <K, V> Map<K, V> convert(java.util.Map<K, V> m) {
    return JavaConverters$.MODULE$.mapAsScalaMapConverter(m).asScala().toMap(
      scala.Predef$.MODULE$.<scala.Tuple2<K, V>>conforms()
    );
  }
}

Writing conversions in Java is a little cleaner with JavaConversions, but on the Scala side essentially everyone hopes that piece of crap will get deprecated as soon as possible, so I'd avoid it even here.

Travis Brown
  • 138,631
  • 12
  • 375
  • 680
  • did you try to use that with a Scala method that takes, say, a `Map[Int, Int]`? Because I'm getting: `actual argument Map cannot be converted to Map by method invocation conversion` – Erik Kaplun Jun 25 '14 at 20:02
  • @ErikAllik, yeah, primitives are another set of headaches, but some `Predef.Integer2int` (or whatever it's called) on the Java side should work. If the OP indicates that they need this, I'll add it to the answer. – Travis Brown Jun 25 '14 at 20:37
  • My post does not fully answer the question, since a java implementation is required. This answer does. upvoted. – Eduardo Briguenti Vieira Jun 25 '14 at 21:55
  • 1
    Awesome Thanks! as a note it does require that you get the latest scala standard library 2.11.0 and conforms appears to have been deprecated. However it works for now and the deprecation issue can be a question for another day! – NSA Jun 25 '14 at 22:27
  • 2
    o, that's scary! Now I see what Kotlin people talk about when the say "java interop" – voddan Jan 26 '16 at 13:56
  • @NSA a slightly different version that works with Scala-2.10 can be found as an answer another question https://stackoverflow.com/a/11903737/638674 – Peter May 20 '16 at 00:20
  • conforms is deprecated now – sil Sep 24 '19 at 08:06
  • @SiLaf Then just use `identity`, it should be exactly the same thing. – Travis Brown Sep 24 '19 at 10:41
  • @TravisBrown sure, but the comment was just there for you to update the answer if you wanted. :) – sil Sep 24 '19 at 10:43
  • @SiLaf I don't want to update it without verifying that the new code works without deprecations on 2.13, and I don't have time to do that at the moment, but thanks. :) – Travis Brown Sep 24 '19 at 10:51