J'écris du code Scala qui utilise l' API Apache POI . Je voudrais parcourir les lignes contenues dans le java.util.Iterator
que je reçois de la classe Sheet. Je voudrais utiliser l'itérateur dans une for each
boucle de style, j'ai donc essayé de le convertir en une collection Scala native mais je n'aurai pas de chance.
J'ai regardé les classes / traits du wrapper Scala, mais je ne vois pas comment les utiliser correctement. Comment parcourir une collection Java dans Scala sans utiliser le while(hasNext()) getNext()
style verbeux de loop?
Voici le code que j'ai écrit en fonction de la bonne réponse:
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
la source
la source
Réponses:
Il existe une classe wrapper (
scala.collection.jcl.MutableIterator.Wrapper
). Donc, si vous définissezalors il agira comme une sous-classe de l'itérateur Scala, donc vous pouvez le faire
foreach
.la source
Depuis Scala 2.8, tout ce que vous avez à faire est d'importer l'objet JavaConversions, qui déclare déjà les conversions appropriées.
Cela ne fonctionnera pas dans les versions précédentes.
la source
Edit : Scala 2.13.0 est obsolète
scala.collection.JavaConverters
, donc depuis la 2.13.0 vous devez utiliserscala.jdk.CollectionConverters
.Scala 2.12.0 est obsolète
scala.collection.JavaConversions
, donc depuis la version 2.12.0, une façon de procéder serait quelque chose comme:(notez l'importation, nouveau est JavaConverters, obsolète est JavaConversions)
la source
La bonne réponse ici est de définir une conversion implicite de Java
Iterator
vers un type personnalisé. Ce type doit implémenter uneforeach
méthode qui délègue au sous-jacentIterator
. Cela vous permettra d'utiliser unefor
boucle Scala avec n'importe quel JavaIterator
.la source
Pour Scala 2.10:
la source
Avec Scala 2.10.4+ (et peut-être plus tôt), il est possible de convertir implicitement java.util.Iterator [A] en scala.collection.Iterator [A] en important scala.collection.JavaConversions.asScalaIterator. Voici un exemple:
la source
Vous pouvez convertir la collection Java en un tableau et l'utiliser:
Ou continuez et convertissez le tableau en une liste Scala:
la source
Si vous effectuez une itération dans un ensemble de données volumineux, vous ne souhaitez probablement pas charger toute la collection en mémoire avec
.asScala
une conversion implicite. Dans ce cas, une approche pratique consiste à implémenter lescala.collection.Iterator
traitIl a un concept similaire mais moins verbeux IMO :)
la source
Si vous souhaitez éviter les implicits dans scala.collection.JavaConversions, vous pouvez utiliser scala.collection.JavaConverters pour convertir explicitement.
Notez l'utilisation de la
asScala
méthode pour convertir le JavaIterator
en ScalaIterator
.Les JavaConverters sont disponibles depuis Scala 2.8.1.
la source
import scala.collection.JavaConverters._
et puisjavaList.iterator().asScala
de votre exemple et cela a fonctionné