Estoy escribiendo un código Scala que usa la API de Apache POI . Me gustaría iterar sobre las filas contenidas en el java.util.Iterator
que obtengo de la clase Hoja. Me gustaría usar el iterador en un for each
bucle de estilo, así que he intentado convertirlo en una colección nativa de Scala, pero no tengo suerte.
He mirado las clases / rasgos de envoltura de Scala, pero no puedo ver cómo usarlas correctamente. ¿Cómo iterar sobre una colección de Java en Scala sin usar el while(hasNext()) getNext()
estilo detallado de bucle?
Aquí está el código que escribí según la respuesta correcta:
class IteratorWrapper[A](iter:java.util.Iterator[A])
{
def foreach(f: A => Unit): Unit = {
while(iter.hasNext){
f(iter.next)
}
}
}
object SpreadsheetParser extends Application
{
implicit def iteratorToWrapper[T](iter:java.util.Iterator[T]):IteratorWrapper[T] = new IteratorWrapper[T](iter)
override def main(args:Array[String]):Unit =
{
val ios = new FileInputStream("assets/data.xls")
val workbook = new HSSFWorkbook(ios)
var sheet = workbook.getSheetAt(0)
var rows = sheet.rowIterator()
for (val row <- rows){
println(row)
}
}
}
java
scala
collections
scala-java-interop
Brian Heylin
fuente
fuente
Respuestas:
Hay una clase contenedora (
scala.collection.jcl.MutableIterator.Wrapper
). Así que si definesentonces actuará como una subclase del iterador Scala para que pueda hacerlo
foreach
.fuente
A partir de Scala 2.8, todo lo que tiene que hacer es importar el objeto JavaConversions, que ya declara las conversiones apropiadas.
Sin embargo, esto no funcionará en versiones anteriores.
fuente
Editar : Scala 2.13.0 está obsoleto
scala.collection.JavaConverters
, por lo que desde 2.13.0 debe usarscala.jdk.CollectionConverters
.Scala 2.12.0 está en desuso
scala.collection.JavaConversions
, por lo que desde 2.12.0 una forma de hacer esto sería algo como:(observe la importación, nuevo es JavaConverters, obsoleto es JavaConversions)
fuente
La respuesta correcta aquí es definir una conversión implícita de Java
Iterator
a algún tipo personalizado. Este tipo debería implementar unforeach
método que delegue al subyacenteIterator
. Esto le permitirá utilizar unfor
bucle de Scala con cualquier JavaIterator
.fuente
Para Scala 2.10:
fuente
Con Scala 2.10.4+ (y posiblemente anterior) es posible convertir implícitamente java.util.Iterator [A] en scala.collection.Iterator [A] importando scala.collection.JavaConversions.asScalaIterator. Aquí hay un ejemplo:
fuente
Puede convertir la colección de Java en una matriz y usar eso:
O continúe y convierta la matriz en una lista Scala:
fuente
Si está iterando a través de un conjunto de datos grande, probablemente no desee cargar la colección completa en la memoria con
.asScala
conversión implícita. En este caso, un enfoque práctico es implementar elscala.collection.Iterator
rasgoTiene un concepto similar pero menos detallado en mi opinión :)
fuente
Si desea evitar las implicaciones en scala.collection.JavaConversions , puede usar scala.collection.JavaConverters para convertir explícitamente.
Tenga en cuenta el uso del
asScala
método para convertir JavaIterator
a ScalaIterator
.Los JavaConverters están disponibles desde Scala 2.8.1.
fuente
import scala.collection.JavaConverters._
y despuésjavaList.iterator().asScala
de su ejemplo y funcionó