Cory Klein
Cory Klein

Reputation: 55620

Convert a Java List of Lists to Scala without O(n) iteration?

Answers to this question do a good job of explaining how to use Scala's Java Converters to change a Java List into a Scala List. Unfortunately, I need to convert a List of Lists from Java to Scala types, and that solution doesn't work:

// pseudocode
java.util.List[java.util.List[String]].asScala
  -> scala.collection.immutable.List[java.util.List[String]]

Is there a way to do this conversion without an O(N) iteration over the Java object?

Upvotes: 1

Views: 894

Answers (2)

Eugene Platonov
Eugene Platonov

Reputation: 3285

alternatively you can use scalaj-collection library i wrote specifically for this purpose

import com.daodecode.scalaj.collection._

val listOfLists: java.util.List[java.util.List[String]] = ...
val s: mutable.Seq[mutable.Seq[String]] = listOfLists.deepAsScala

that's it. It will convert all nested java collections and primitive types to scala versions. You can also convert directly to immutable data structures using deepAsScalaImmutable (with some copying overhead of course)

Upvotes: 0

Angelo Genovese
Angelo Genovese

Reputation: 3398

You need to convert the nested lists as well, but that would require the up front O(n):

import scala.collection.JavaConverters._

val javaListOfLists = List(List("a", "b", "c").asJava, List("d", "e", "f").asJava).asJava
val scalaListOfLists = javaListOfLists.asScala.toList.map(_.asScala.toList)

Alternatively, you could convert the outer list into a Stream[List[T]], that would only apply the conversion cost as you accessed each item

val scalaStreamOfLists = javaListOfLists.asScala.toStream.map(_.asScala.toList)

If you don't want to pay the conversion cost at all, you could write a wrapper around java.util.List which would give you a scala collection interface. a rought shot at that would be:

def wrap[T](javaIterator: java.util.Iterator[T]): Stream[T] = {
  if (javaIterator.hasNext)
    javaIterator.next #:: wrap(javaIterator)
  else
    empty
}

val outerWrap = wrap(javaListOfLists.iterator).map(inner => wrap(inner.iterator()))

Upvotes: 3

Related Questions