I have some Scala code that interops with Java code. I had previously used
import scala.collection.JavaConversions._
to support auto-conversion of collections, allowing me to call a method expecting a Java collection by passing it a Scala collection, and the other way around.
Today I refactored my code so this conversion happens explicitly.
I got rid of the JavaConversions import and instead added this:
import scala.collection.JavaConverters._
Then whenever I need code that expects a Java collection but I have a Scala collection, I call myScalaCollection.asJava, and when I do it the other way around, I call myJavaCollection.asScala.
It's less verbose and perhaps less magical, but I think it's easier to read the code and see what is going on. I'm controlling the conversion instead of letting the compiler do it for me, so I can be aware of any performance issues, etc. of possibly converting something back and forth needlessly.
There are some limitations. When you have a Scala queue, for example, a scala.collection.immutable.Queue[T], calling the implicit method .asJava converts it to a java.util.List, which is not exactly a queue! If you want a Java Queue, you'd have to new java.util.LinkedList(myScalaQueue.asJava), because LinkedList implements the Java Queue interface and takes in a java.util.List as a constructor argument.
It is also possible to implement this yourself by creating your own implicit method, e.g.:
import scala.collection.JavaConverters._
import scala.collection.Seq
import java.util.LinkedList
object ScalaSeqHelper {
implicit class SeqImplicits(seq: Seq) {
def asJavaLinkedList: LinkedList = {
new LinkedList(seq.asJava)
}
}
}
Then if you import ScalaSeqHelper._, you can call .asJavaLinkedList on any Scala Seq (which includes the mutable and immutable Queue implementations) and get a Java LinkedList, which is also a Java Queue.
No comments:
Post a Comment