I\'m writing some Scala code which uses the Apache POI API. I would like to iterate over the rows contained in the java.util.Iterator
that I get from the Sheet
The correct answer here is to define an implicit conversion from Java's Iterator
to some custom type. This type should implement a foreach
method which delegates to the underlying Iterator
. This will allow you to use a Scala for
-loop with any Java Iterator
.
You could convert the Java collection to an array and use that:
val array = java.util.Arrays.asList("one","two","three").toArray
array.foreach(println)
Or go on and convert the array to a Scala list:
val list = List.fromArray(array)
If you would like to avoid the implicits in scala.collection.JavaConversions you can use scala.collection.JavaConverters to convert explicitly.
scala> val l = new java.util.LinkedList[Int]()
l: java.util.LinkedList[Int] = []
scala> (1 to 10).foreach(l.add(_))
scala> val i = l.iterator
i: java.util.Iterator[Int] = java.util.LinkedList$ListItr@11eadcba
scala> import scala.collection.JavaConverters._
import scala.collection.JavaConverters._
scala> i.asScala.mkString
res10: String = 12345678910
Note the use of the asScala
method to convert the Java Iterator
to a Scala Iterator
.
The JavaConverters have been available since Scala 2.8.1.
With Scala 2.10.4+ (and possibly earlier) it is possible to implicitly convert java.util.Iterator[A] to scala.collection.Iterator[A] by importing scala.collection.JavaConversions.asScalaIterator. Here is an example:
object SpreadSheetParser2 extends App {
import org.apache.poi.hssf.usermodel.HSSFWorkbook
import java.io.FileInputStream
import scala.collection.JavaConversions.asScalaIterator
val ios = new FileInputStream("data.xls")
val workbook = new HSSFWorkbook(ios)
var sheet = workbook.getSheetAt(0)
val rows = sheet.rowIterator()
for (row <- rows) {
val cells = row.cellIterator()
for (cell <- cells) {
print(cell + ",")
}
println
}
}
For Scala 2.10:
// Feature warning if you don't enable implicit conversions...
import scala.language.implicitConversions
import scala.collection.convert.WrapAsScala.enumerationAsScalaIterator
Edit: Scala 2.13.0 deprecates scala.collection.JavaConverters
, so since 2.13.0 you need to use scala.jdk.CollectionConverters
.
Scala 2.12.0 deprecates scala.collection.JavaConversions
, so since 2.12.0 one way of doing this would be something like:
import scala.collection.JavaConverters._
// ...
for(k <- javaCollection.asScala) {
// ...
}
(notice the import, new is JavaConverters, deprecated is JavaConversions)