스칼라에서 Java 컬렉션을 반복
Apache POI API 를 사용하는 스칼라 코드를 작성 중 입니다. java.util.Iterator
Sheet 클래스에서 얻은 행에 포함 된 행을 반복하고 싶습니다 . for each
스타일 루프 에서 반복자를 사용하고 싶습니다 . 그래서 네이티브 스칼라 컬렉션으로 변환하려고했지만 운이 없습니다.
스칼라 래퍼 클래스 / 특성을 살펴 보았지만 올바르게 사용하는 방법을 알 수 없습니다. 장황한 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)
}
}
}
랩퍼 클래스 ( scala.collection.jcl.MutableIterator.Wrapper
)가 있습니다. 따라서 정의하면
implicit def javaIteratorToScalaIterator[A](it : java.util.Iterator[A]) = new Wrapper(it)
그러면 스칼라 반복기의 하위 클래스로 작동하여 수행 할 수 있습니다 foreach
.
Scala 2.8부터 JavaConversions 객체를 가져 오기만하면됩니다.이 객체는 이미 적절한 변환을 선언합니다.
import scala.collection.JavaConversions._
이전 버전에서는 작동하지 않습니다.
편집 : Scala 2.13.0은 더 이상 사용되지 않으므로 scala.collection.JavaConverters
2.13.0부터 사용해야 scala.jdk.CollectionConverters
합니다.
Scala 2.12.0은 더 이상 사용되지 않으므로 2.12.0 scala.collection.JavaConversions
이후로이를 수행하는 한 가지 방법은 다음과 같습니다.
import scala.collection.JavaConverters._
// ...
for(k <- javaCollection.asScala) {
// ...
}
(가져 오기에 대한 새로운 사항은 JavaConverters이며, 더 이상 사용되지 않음은 JavaConversions입니다.)
정답은 Java에서 Iterator
일부 사용자 정의 유형으로 의 암시 적 변환을 정의하는 것 입니다. 이 형식은 foreach
기본에 위임 하는 메서드를 구현해야합니다 Iterator
. 이것에 for
의해, Java와 함께 스칼라 루프 를 사용할 수 있습니다 Iterator
.
스칼라 2.10의 경우 :
// Feature warning if you don't enable implicit conversions...
import scala.language.implicitConversions
import scala.collection.convert.WrapAsScala.enumerationAsScalaIterator
With Scala 2.10.4+ (and possibly earlier) it is possible to implicitly convert java.util.Iterator[A] to scala.collection.Iterator[A] by importing scala.collection.JavaConversions.asScalaIterator. Here is an example:
object SpreadSheetParser2 extends App {
import org.apache.poi.hssf.usermodel.HSSFWorkbook
import java.io.FileInputStream
import scala.collection.JavaConversions.asScalaIterator
val ios = new FileInputStream("data.xls")
val workbook = new HSSFWorkbook(ios)
var sheet = workbook.getSheetAt(0)
val rows = sheet.rowIterator()
for (row <- rows) {
val cells = row.cellIterator()
for (cell <- cells) {
print(cell + ",")
}
println
}
}
You could convert the Java collection to an array and use that:
val array = java.util.Arrays.asList("one","two","three").toArray
array.foreach(println)
Or go on and convert the array to a Scala list:
val list = List.fromArray(array)
If you are iterating through a large dataset, then you probably don't want to load whole collection into memory with .asScala
implicit conversion. In this case, a handy way approach is to implement scala.collection.Iterator
trait
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
It has similar concept but less verbose IMO :)
If you would like to avoid the implicits in scala.collection.JavaConversions you can use scala.collection.JavaConverters to convert explicitly.
scala> val l = new java.util.LinkedList[Int]()
l: java.util.LinkedList[Int] = []
scala> (1 to 10).foreach(l.add(_))
scala> val i = l.iterator
i: java.util.Iterator[Int] = java.util.LinkedList$ListItr@11eadcba
scala> import scala.collection.JavaConverters._
import scala.collection.JavaConverters._
scala> i.asScala.mkString
res10: String = 12345678910
Note the use of the asScala
method to convert the Java Iterator
to a Scala Iterator
.
The JavaConverters have been available since Scala 2.8.1.
참고URL : https://stackoverflow.com/questions/495741/iterating-over-java-collections-in-scala
'development' 카테고리의 다른 글
FlowLayout으로 UICollectionView의 높이를 결정하는 방법 (0) | 2020.07.30 |
---|---|
Intellij IDEA 14에서 원격 저장소 자격 증명 (인증) 변경 (0) | 2020.07.30 |
Heroku 푸시 거부, 시더 지원 앱이 감지되지 않음 (0) | 2020.07.30 |
C #에서 DateTime을 확인하는 방법? (0) | 2020.07.30 |
iPhone에서 $ (document) .click ()이 올바르게 작동하지 않습니다. (0) | 2020.07.30 |