1. Overview
While working on applications in Scala, we may have to interact with a library that’s only compiled in Java. This can make things difficult in our existing code, as we may have a function that requires a Scala data type, but the Java library only provides us with a Java type.
In this tutorial, we’ll explore how to circumvent this problem for collections and effectively convert a Java List into Scala Seq for use in our application code.
2. Using Below Scala 2.13.0
Before version 2.13.0, the Scala standard library offered the JavaConverts object, for conversions between Java and Scala data structures. JavaConverters offers a variety of functions depending on what data type we need to convert.
For Java List, we can use collectionAsScalaIterable:
val list: util.List[String] = util.ArrayList[String]()
val scalaSeq: Seq[String] = JavaConverters.collectionAsScalaIterable(list).toSeq
Here we’re calling JavaConverters.collectionAsScalaIterable and passing in the Java ArrayList[String] as the argument. Then, calling toSeq on the result returns a Scala type of Seq[String]. We can see this from the type annotation of the scalaSeq variable.
3. Using Scala 2.13.0 or Above
From Scala 2.13 onwards, the JavaConverters object was deprecated and replaced with CollectionConverters. This object contains an overloaded function; asScala. Which, has implementations that replace all the individual AsScala functions that the JavaConverters object offered.
This makes using the CollectionConverters a lot easier as we can simply call asScala and the compiler works out which implementation is required from the argument we provide. Let’s see how CollectionConverters compares:
val list: util.List[String] = util.ArrayList[String]()
val scalaSeq: Seq[String] = CollectionConverters.asScala(list).toSeq
In this example, we can see CollectionConverters.asScala behaves almost identically to the deprecated JavaConverters.collectionAsScalaIterable call from pre-2.13.0 Scala.
After calling CollectionConverters.asScala and passing in the Java ArrayList[String] we can again call toSeq on the result to transform it into a Scala Seq[String].
4. Converting to Other Collections
The call to *CollectionConverters.*asScala has a return type of Buffer, which extends a lot of the Scala collections. This means we can convert most collections by calling asScala(). In previous examples, we’ve converted to a Seq, but we could convert to many other collection types:
val list: util.List[String] = util.ArrayList[String]()
val scalaList: List[String] = CollectionConverters.asScala(list).toList
val scalaSet: Set[String] = CollectionConverters.asScala(list).toSet
val scalaIndexedSeq: IndexedSeq[String] = CollectionConverters.asScala(list).toIndexedSeq
val scalaVector: Vector[String] = CollectionConverters.asScala(list).toVector
Additionally, since JavaConverters.collectionAsScalaIterable converts to an Iterable, we can do the same in pre-2.13.0 Scala:
val list: util.List[String] = util.ArrayList[String]()
val scalaList: List[String] = JavaConverters.collectionAsScalaIterable(list).toList
val scalaSet: Set[String] = JavaConverters.collectionAsScalaIterable(list).toSet
val scalaIndexedSeq: IndexedSeq[String] = JavaConverters.collectionAsScalaIterable(list).toIndexedSeq
val scalaVector: Vector[String] = JavaConverters.collectionAsScalaIterable(list).toVector
5. Conclusion
In this article, we have discovered how to convert a Java List into a Scala Seq. We know how to do this for applications in Scala versions lower than 2.13.0 using JavaConverters. Then, we also know to use CollectionConverters for any Scala code running version 2.13.0 or above.
Finally, we discussed the range of other Scala collections we can convert to using the *CollectionConverters.*asScala or JavaConverters.collectionAsScalaIterable functions.
As always, the sample code used in this article is available over on GitHub.