116 votes

Itération sur des collections Java en Scala

Je suis en train d'écrire un code Scala qui utilise la fonction POI Apache API. Je voudrais itérer sur les lignes contenues dans le fichier java.util.Iterator que je reçois de la classe de feuille. Je voudrais utiliser l'itérateur dans un fichier de type for each J'ai donc essayé de la convertir en une collection native Scala, mais sans succès.

J'ai examiné les classes/traits de wrapper Scala, mais je ne vois pas comment les utiliser correctement. Comment puis-je itérer sur une collection Java en Scala sans utiliser la fonction verbose ? while(hasNext()) getNext() style de boucle ?

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)
        }
    }
}

0 votes

Je n'arrive pas à inclure la ligne "for (val row <- rows){" sans que l'analyseur pense que le caractère '<' est une balise de fermeture XML ? Les barres obliques inversées ne fonctionnent pas.

0 votes

Vous devriez être en mesure de convertir en IteratirWrapper de manière implicite, ce qui vous permettra d'économiser une bonne partie de la syntaxe. Cherchez sur Google les conversions implicites en Scala.

259voto

ttonelli Points 1

À partir de Scala 2.8, il suffit d'importer l'objet JavaConversions, qui déclare déjà les conversions appropriées.

import scala.collection.JavaConversions._

Cela ne fonctionnera pas dans les versions précédentes.

36voto

antonone Points 310

Modifier : Scala 2.13.0 déprécié scala.collection.JavaConverters donc, depuis la version 2.13.0, vous devez utiliser l'option scala.jdk.CollectionConverters .

Scala 2.12.0 déprécié scala.collection.JavaConversions Donc, depuis la version 2.12.0, une façon de procéder serait la suivante :

import scala.collection.JavaConverters._

// ...

for(k <- javaCollection.asScala) {
    // ...
}

(remarquez l'importation, nouveau est JavaConverters, déprécié est JavaConversions)

29voto

Il existe une classe d'enveloppe ( scala.collection.jcl.MutableIterator.Wrapper ). Ainsi, si vous définissez

implicit def javaIteratorToScalaIterator[A](it : java.util.Iterator[A]) = new Wrapper(it)

alors il agira comme une sous-classe de l'itérateur Scala et vous pourrez faire foreach .

15voto

Daniel Spiewak Points 30706

La réponse correcte ici est de définir une conversion implicite à partir du langage Java Iterator à un type personnalisé. Ce type doit implémenter un foreach qui délègue à la méthode sous-jacente Iterator . Cela vous permettra d'utiliser un programme Scala for -boucle avec n'importe quel Java Iterator .

9voto

F. P. Freely Points 74

Pour Scala 2.10 :

// Feature warning if you don't enable implicit conversions...
import scala.language.implicitConversions
import scala.collection.convert.WrapAsScala.enumerationAsScalaIterator

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X