Java <-> Scala interop: transparent List and Map conversion

Viewed 10562

I am learning Scala and I have a Java project to migrate to Scala. I want to migrate it by rewriting classes one-by-one and checking that new class didn't break the project.

This Java project uses lots of java.util.List and java.util.Map. In new Scala classes I would like to use Scala’s List and Map to have good-looking Scala code.

The problem is that new classes (those are wtitten in Scala) do not integrate seamelessly with existing Java code: Java needs java.util.List, Scala needs its own scala.List.

Here is a simplified example of the problem. There are classes Main, Logic, Dao. They call each other in a line: Main -> Logic -> Dao.

public class Main {
    public void a() {
        List<Integer> res = new Logic().calculate(Arrays.asList(1, 2, 3, 4, 5));
    }
}

public class Logic {
    public List<Integer> calculate(List<Integer> ints) {
        List<Integer> together = new Dao().getSomeInts();
        together.addAll(ints);
        return together;
    }
}

public class Dao {
    public List<Integer> getSomeInts() {
        return Arrays.asList(1, 2, 3);
    }
}

In my situation, classes Main and Dao are framework classes (I don’t need to migrate them). Class Logic is business-logic and will benefit a lot from Scala cool features.

I need to rewrite class Logic in Scala while preserving integrity with classes Main and Dao. The best rewrite would look like (doesn’t work):

class Logic2 {
  def calculate(ints: List[Integer]) : List[Integer] = {
      val together: List[Integer] = new Dao().getSomeInts()
      together ++ ints
  }
}

Ideal behaviour: Lists inside Logic2 are native Scala Lists. All in/out java.util.Lists get boxed/unboxed automagically. But this doesn't work.

Instead, this does work (thanks to scala-javautils (GitHub)):

import org.scala_tools.javautils.Implicits._

class Logic3 {
  def calculate(ints: java.util.List[Integer]) : java.util.List[Integer] = {
      val together: List[Integer] = new Dao().getSomeInts().toScala
      (together ++ ints.toScala).toJava
  }
}

But it looks ugly.

How do I achieve transparent magic conversion of Lists and Maps between Java <-> Scala (without need to do toScala/toJava)?

If it is not possible, what are the best practices for migrating Java -> Scala code that uses java.util.List and friends?

3 Answers
Related