3

I want to convert my java map into a Scala immutable map, I have a sample code that works correctly with Scala 2.12 but fails with Scala 2.13.

Setup

untitled14\build.sbt

name := "untitled14"
version := "0.1"
scalaVersion := "2.12.13"

untitled14\project\build.properties

sbt.version = 1.4.1

untitled14\src\main\java\Main.java

import scala.Predef;
import scala.Tuple2;
import scala.collection.JavaConverters;

import java.util.HashMap;
import java.util.Map;

public class Main {

    public static void main(String[] args) {

        Map<Integer, String> javaMap = new HashMap<>();
        javaMap.put(1, "java");
        javaMap.put(2, "scala");
        javaMap.put(3, "js");

        System.out.println("Java map -> " + javaMap);

        scala.collection.immutable.Map<Integer, String> scalaMap = JavaConverters
                .mapAsScalaMapConverter(javaMap)
                .asScala()
                .toMap(Predef.<Tuple2<Integer, String>>conforms());

        System.out.println("Scala map -> " + scalaMap);
    }
}

The command I have executed

sbt run

Output

Java map -> {1=java, 2=scala, 3=js}
Scala map -> Map(1 -> java, 2 -> scala, 3 -> js)

So, you can see from the above that the code works 100% correctly.

Now if I update my build.sbt to use scala-2.13.3 there would be a compilation error.

untitled14\build.sbt

name := "untitled14"
version := "0.1"
scalaVersion := "2.13.3"

The command I have executed

sbt clean compile

Output

compile

[info] compiling 1 Java source to D:\untitled14\target\scala-2.13\classes ...
[error] D:\untitled14\src\main\java\Main.java:22:1: cannot find symbol
[error]   symbol:   method <scala.Tuple2<java.lang.Integer,java.lang.String>>conforms()
[error]   location: class scala.Predef
[error] Predef.<Tuple2<Integer, String>>conforms
[error] (Compile / compileIncremental) javac returned non-zero exit code
[error] Total time: 1 s, completed 15-Jan-2021, 6:01:18 pm

I tried using

import scala.jdk.CollectionConverters;

import java.util.HashMap;
import java.util.Map;

public class Main {

    public static void main(String[] args) {

        Map<Integer, String> javaMap = new HashMap<>();
        javaMap.put(1, "java");
        javaMap.put(2, "scala");
        javaMap.put(3, "js");

        System.out.println("Java map -> " + javaMap);

        scala.collection.immutable.Map<Integer, String> scalaMap = CollectionConverters
                .MapHasAsScala(javaMap)
                .asScala()
                .toMap(scala.$less$colon$less.refl());

        System.out.println("Scala map -> " + scalaMap);
    }
}

but got the error output as

[info] compiling 1 Java source to D:\untitled14\target\scala-2.13\classes ...
[error] D:\untitled14\src\main\java\Main.java:20:1: cannot find symbol
[error]   symbol:   method refl()
[error]   location: class scala.$less$colon$less
[error] scala.$less$colon$less.refl
[error] (Compile / compileIncremental) javac returned non-zero exit code
[error] Total time: 1 s, completed 15-Jan-2021, 6:06:43 pm

Can some let me know how to do it correctly?

Note:- I am using jvm-14, sbt-1.4.1, scala-2.13.3

Divyanshu
  • 290
  • 2
  • 9
  • There is no concept of implicit inside java code. Implicits are meaning full only inside scala code. – Divyanshu Jan 15 '21 at 12:50
  • 2
    It is usually easier to write a Scala function that does the transformation and call that from Java. – Luis Miguel Mejía Suárez Jan 15 '21 at 12:56
  • That's merely a trick to do that, if we can do that with scala-2.12 then it should also be possible to do with scala-2.13. Writing a function in scala and calling it from java is just overhead in my opinion. @LuisMiguelMejíaSuárez – Divyanshu Jan 15 '21 at 13:00

2 Answers2

5

You have a very simple solution in Scala 2.13:

scala.collection.immutable.Map<Integer, String> scalaMap =
        scala.collection.immutable.Map.from(scala.jdk.CollectionConverters.MapHasAsScala(javaMap).asScala());
Tomer Shetah
  • 8,413
  • 7
  • 27
  • 35
2

Found the solution on my own just use $less$colon$less$.MODULE$.refl() instead of Predef.<Tuple2<Integer, String>>conforms()

import scala.$less$colon$less$;
import scala.jdk.CollectionConverters;

import java.util.HashMap;
import java.util.Map;

public class Main {

    public static void main(String[] args) {

        Map<Integer, String> javaMap = new HashMap<>();
        javaMap.put(1, "java");
        javaMap.put(2, "scala");
        javaMap.put(3, "js");

        System.out.println("Java map -> " + javaMap);

        scala.collection.immutable.Map<Integer, String> scalaMap = CollectionConverters
                .MapHasAsScala(javaMap)
                .asScala()
                .toMap($less$colon$less$.MODULE$.refl());

        System.out.println("Scala map -> " + scalaMap);
    }
}
Divyanshu
  • 290
  • 2
  • 9