Ich schreibe einen Scala-Code, der die Apache POI- API verwendet. Ich möchte über die Zeilen iterieren, die in java.util.Iterator
der Sheet-Klasse enthalten sind. Ich möchte den Iterator in einer for each
Stilschleife verwenden, daher habe ich versucht, ihn in eine native Scala-Sammlung zu konvertieren, werde aber kein Glück haben.
Ich habe mir die Scala-Wrapper-Klassen / -Eigenschaften angesehen, kann aber nicht sehen, wie man sie richtig verwendet. Wie iteriere ich über eine Java-Sammlung in Scala, ohne den ausführlichen while(hasNext()) getNext()
Stil der Schleife zu verwenden?
Hier ist der Code, den ich basierend auf der richtigen Antwort geschrieben habe:
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
quelle
quelle
Antworten:
Es gibt eine Wrapper-Klasse (
scala.collection.jcl.MutableIterator.Wrapper
). Also, wenn Sie definierenDann fungiert es als Unterklasse des Scala-Iterators, sodass Sie dies tun können
foreach
.quelle
Ab Scala 2.8 müssen Sie lediglich das JavaConversions-Objekt importieren, das bereits die entsprechenden Konvertierungen deklariert.
Dies funktioniert jedoch in früheren Versionen nicht.
quelle
Bearbeiten : Scala 2.13.0 ist veraltet
scala.collection.JavaConverters
, daher müssen Sie seit 2.13.0 verwendenscala.jdk.CollectionConverters
.Scala 2.12.0 ist veraltet
scala.collection.JavaConversions
. Seit 2.12.0 wäre eine Möglichkeit, dies zu tun, etwa:(Beachten Sie den Import, neu ist JavaConverters, veraltet ist JavaConversions)
quelle
Die richtige Antwort besteht darin, eine implizite Konvertierung von Java
Iterator
in einen benutzerdefinierten Typ zu definieren. Dieser Typ sollte eineforeach
Methode implementieren , die an den Basiswert delegiertIterator
. Auf diese Weise können Sie eine Scala-for
Schleife mit jedem Java verwendenIterator
.quelle
Für Scala 2.10:
quelle
Mit Scala 2.10.4+ (und möglicherweise früher) ist es möglich, java.util.Iterator [A] implizit in scala.collection.Iterator [A] zu konvertieren, indem scala.collection.JavaConversions.asScalaIterator importiert wird. Hier ist ein Beispiel:
quelle
Sie können die Java-Sammlung in ein Array konvertieren und Folgendes verwenden:
Oder konvertieren Sie das Array in eine Scala-Liste:
quelle
Wenn Sie ein großes Dataset durchlaufen, möchten Sie wahrscheinlich nicht die gesamte Sammlung mit
.asScala
impliziter Konvertierung in den Speicher laden . In diesem Fall besteht ein praktischer Ansatz darin,scala.collection.Iterator
Merkmale zu implementierenEs hat ein ähnliches Konzept, aber weniger ausführlich IMO :)
quelle
Wenn Sie die Implikationen in scala.collection.JavaConversions vermeiden möchten, können Sie scala.collection.JavaConverters verwenden , um explizit zu konvertieren.
Beachten Sie die Verwendung der
asScala
Methode zum Konvertieren von JavaIterator
in eine ScalaIterator
.Die JavaConverter sind seit Scala 2.8.1 verfügbar.
quelle
import scala.collection.JavaConverters._
und dannjavaList.iterator().asScala
von Ihrem Beispiel und es hat funktioniert