While working on a new Scala application, I just ran into a situation where a Java class I was using returned a Java List to me. I wasn't exactly thinking too hard at that moment, and didn't realize it was actually a Java List until I tried to use the foreach method on it, and Eclipse balked at me.
Suddenly I ran into a common problem in Scala: When you're using Java classes from Scalaapplications, those Java class will return Java collections. You can then either use them as the Java collections that they are (such as using a Java Iterator), or cast them to Scala collections.
Easily converting Java collections to Scala collections
Amazingly, to use methods like foreach, map, filter, find, and so on with my Java List, all I had to do was add this one import statement to my Scala application:
import scala.collection.JavaConversions._
Once I did that, I could suddenly use a foreach method on my List.
Let's take a quick look at how this works with the Scala command line tool (the Scala REPL). First, we'll create a java.util.List as normal, and see what the REPL shows:
scala> var list = new java.util.ArrayList[Int]() list: java.util.ArrayList[Int] = [] scala> list.add(1) res1: Boolean = true scala> list.add(2) res2: Boolean = true
Now, if I try to use the foreach method on the Java list, it will fail, as expected:
scala> list.foreach <console>:9: error: value foreach is not a member of java.util.ArrayList[Int] list.foreach ^
However, if I now add the magic JavaConversions import statement to my Scala code:
import scala.collection.JavaConversions._
I can then "magically" use the foreach method on my Java List object:
list.foreach { i => println(i) } 1 2
Scala, Java List, foreach, map, filter - How it works
I just started learning Scala in 2011, and it looks like programmers long before me realized the need for the Java to Scala collection conversions, and added this functionality in Scala 2.8. I haven't dug into the source code behind the scenes to see how this magic works, but I just found a nice discussion of the background at the Graham Hacking Scala website.
Graham mentions several interesting points in that article, including these notes:
If we look a bit further into the Scala API, we'll see that there's also a trait called Seq, which is a slightly better parallel to Java's List than the Iterable or Traversable traits. So what you really want to end up with when you bring your Java List into your Scala code is a Scala Seq, not a Scala List.
Conversions between Java and Scala collections with JavaConversions
While I'm on this topic, I'll conclude with a few links to the Scala website, where you can find more information:
As you can see from that second link, the JavaConversions object currently supports the following Java to Scala collections conversions:
scala.collection.Iterable <=> java.lang.Iterable scala.collection.Iterable <=> java.util.Collection scala.collection.Iterator <=> java.util.{ Iterator, Enumeration } scala.collection.mutable.Buffer <=> java.util.List scala.collection.mutable.Set <=> java.util.Set scala.collection.mutable.Map <=> java.util.{ Map, Dictionary } scala.collection.mutable.ConcurrentMap <=> java.util.concurrent.ConcurrentMap
Important for my current project, the following one-way conversions are also offered:
scala.collection.Seq => java.util.List scala.collection.mutable.Seq => java.util.List scala.collection.Set => java.util.Set scala.collection.Map => java.util.Map java.util.Properties => scala.collection.mutable.Map[String, String]
In summary, I hope this brief tutorial on converting Java collections, such as a List, to Scala collections, has been helpful.