116

ApachePOIAPIを使用するScalaコードを書いています。java.util.IteratorSheetクラスから取得したに含まれる行を繰り返し処理したいと思います。イテレータをスタイルループで使用したいfor eachので、ネイティブのScalaコレクションに変換しようとしましたが、うまくいきません。

Scalaラッパーのクラス/特性を見てきましたが、正しく使用する方法がわかりません。while(hasNext()) getNext()冗長なスタイルのループを使用せずに、ScalaでJavaコレクションを反復処理するにはどうすればよいですか?

正解に基づいて作成したコードは次のとおりです。

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

9 に答える 9

258

Scala 2.8以降、あなたがしなければならないのは、適切な変換をすでに宣言しているJavaConversionsオブジェクトをインポートすることだけです。

import scala.collection.JavaConversions._

ただし、これは以前のバージョンでは機能しません。

于 2009-10-26T14:45:34.197 に答える
29

ラッパー クラス ( scala.collection.jcl.MutableIterator.Wrapper) があります。したがって、定義すると

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

次に、Scala イテレーターのサブクラスとして機能するので、実行できますforeach

于 2009-08-03T16:24:41.310 に答える
15

ここでの正解は、JavaIteratorから何らかのカスタム型への暗黙的な変換を定義することです。foreachこの型は、基になる に委譲するメソッドを実装する必要がありIteratorます。forこれにより、任意の Javaで Scala ループを使用できるようになりますIterator

于 2009-01-30T15:48:24.723 に答える
9

Scala 2.10の場合:

// Feature warning if you don't enable implicit conversions...
import scala.language.implicitConversions
import scala.collection.convert.WrapAsScala.enumerationAsScalaIterator
于 2013-02-21T18:01:26.733 に答える
5

.asScala大規模なデータセットを反復処理している場合は、コレクション全体を暗黙的な変換でメモリにロードしたくないでしょう。この場合、便利な方法はscala.collection.Iteratortraitを実装することです

import java.util.{Iterator => JIterator}

def scalaIterator[T](it: JIterator[T]) = new Iterator[T] {
  override def hasNext = it.hasNext
  override def next() = it.next()
} 

val jIterator: Iterator[String] = ... // iterating over a large dataset
scalaIterator(jIterator).take(2).map(_.length).foreach(println)  // only first 2 elements are loaded to memory

コンセプトは似ていますが、IMO はあまり詳しくありません :)

于 2016-01-01T00:43:51.373 に答える