Scala LanguageJava Interoperability

Converting Scala Collections to Java Collections and vice versa

When you need to pass a collection into a Java method:

import scala.collection.JavaConverters._

val scalaList = List(1, 2, 3)

If the Java code returns a Java collection, you can turn it into a Scala collection in a similar manner:

import scala.collection.JavaConverters._

val javaCollection = JavaLibrary.getList
val scalaCollection = javaCollection.asScala

Note that these are decorators, so they merely wrap the underlying collections in a Scala or Java collection interface. Therefore, the calls .asJava and .asScala do not copy the collections.


Arrays are regular JVM arrays with a twist that they are treated as invariant and have special constructors and implicit conversions. Construct them without the new keyword.

 val a = Array("element")

Now a has type Array[String].

 val acs: Array[CharSequence] = a
 //Error: type mismatch;  found   : Array[String]  required: Array[CharSequence]

Although String is convertible to CharSequence, Array[String] is not convertible to Array[CharSequence].

You can use an Array like other collections, thanks to an implicit conversion to TraversableLike ArrayOps:

 val b: Array[Int] =

Most of the Scala collections (TraversableOnce) have a toArray method taking an implicit ClassTag to construct the result array:

 //> res1: Array[Int] = Array(0)

This makes it easy to use any TraversableOnce in your Scala code and then pass it to Java code which expects an array.

Scala and Java type conversions

Scala offers implicit conversions between all the major collection types in the JavaConverters object.

The following type conversions are bidirectional.

Scala TypeJava Type

Certain other Scala collections can also be converted to Java, but do not have a conversion back to the original Scala type:

Scala TypeJava Type


Conversions Between Java and Scala Collections

Functional Interfaces for Scala functions - scala-java8-compat

A Java 8 compatibility kit for Scala.

Most examples are copied from Readme

Converters between scala.FunctionN and java.util.function

import java.util.function._
import scala.compat.java8.FunctionConverters._

val foo: Int => Boolean = i => i > 7
def testBig(ip: IntPredicate) = ip.test(9)
println(testBig(foo.asJava))  // Prints true

val bar = new UnaryOperator[String]{ def apply(s: String) = s.reverse }
List("cod", "herring").map(bar.asScala)    // List("doc", "gnirrih")

def testA[A](p: Predicate[A])(a: A) = p.test(a)
println(testA(asJavaPredicate(foo))(4))  // Prints false

Converters between scala.Option and java.util classes Optional, OptionalDouble, OptionalInt, and OptionalLong.

import scala.compat.java8.OptionConverters._

    class Test {
      val o = Option(2.7)
      val oj = o.asJava        // Optional[Double]
      val ojd = o.asPrimitive  // OptionalDouble
      val ojds = ojd.asScala   // Option(2.7) again

Converters from Scala collections to Java 8 Streams


import scala.compat.java8.StreamConverters._
import scala.compat.java8.collectionImpl.{Accumulator, LongAccumulator}

  val m = collection.immutable.HashMap("fish" -> 2, "bird" -> 4)
  val parStream: IntStream = m.parValueStream
  val s: Int = parStream.sum
  // 6, potientially computed in parallel
  val t: List[String] = m.seqKeyStream.toScala[List]
  // List("fish", "bird")
  val a: Accumulator[(String, Int)] = m.accumulate // Accumulator[(String, Int)]

  val n = a.stepper.fold(0)(_ + _._1.length) +
    a.parStream.count // 8 + 2 = 10

  val b: LongAccumulator =, 3L, 4L)).accumulate
  // LongAccumulator
  val l: List[Long] =[List] // List(2L, 3L, 4L)