Piszę trochę kodu Scala, który wykorzystuje API Apache POI . Chciałbym iterować po wierszach zawartych w tym, java.util.Iterator
które otrzymałem z klasy Sheet. Chciałbym użyć iteratora w for each
pętli stylów, więc próbowałem przekonwertować go na natywną kolekcję Scala, ale bez powodzenia.
Przyjrzałem się klasom / cechom opakowania Scala, ale nie widzę, jak ich poprawnie używać. Jak iterować kolekcję Java w Scali bez używania szczegółowego while(hasNext()) getNext()
stylu pętli?
Oto kod, który napisałem na podstawie poprawnej odpowiedzi:
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
źródło
źródło
Odpowiedzi:
Istnieje klasa opakowująca (
scala.collection.jcl.MutableIterator.Wrapper
). Więc jeśli zdefiniujeszwtedy będzie działać jako podklasa iteratora Scala, więc możesz to zrobić
foreach
.źródło
Od wersji Scala 2.8 wszystko, co musisz zrobić, to zaimportować obiekt JavaConversions, który już deklaruje odpowiednie konwersje.
To nie zadziała jednak w poprzednich wersjach.
źródło
Edycja : Scala 2.13.0 jest przestarzała
scala.collection.JavaConverters
, więc od 2.13.0 musisz użyćscala.jdk.CollectionConverters
.Scala 2.12.0 jest przestarzała
scala.collection.JavaConversions
, więc od wersji 2.12.0 jednym ze sposobów byłoby coś takiego:(zwróć uwagę na import, nowy to JavaConverters, przestarzały to JavaConversions)
źródło
Poprawną odpowiedzią jest tutaj zdefiniowanie niejawnej konwersji z języka Java na
Iterator
typ niestandardowy. Ten typ powinien implementowaćforeach
metodę, która jest delegowana do bazowegoIterator
. Umożliwi to użyciefor
pętli Scala z dowolną JavąIterator
.źródło
Dla Scala 2.10:
źródło
Ze Scala 2.10.4+ (i prawdopodobnie wcześniejszą) można niejawnie przekonwertować java.util.Iterator [A] na scala.collection.Iterator [A], importując scala.collection.JavaConversions.asScalaIterator. Oto przykład:
źródło
Możesz przekonwertować kolekcję Java na tablicę i użyć tego:
Lub przejdź dalej i przekonwertuj tablicę na listę Scala:
źródło
Jeśli przeglądasz duży zestaw danych, prawdopodobnie nie chcesz ładować całej kolekcji do pamięci za pomocą
.asScala
niejawnej konwersji. W tym przypadku wygodnym sposobem jest zaimplementowaniescala.collection.Iterator
cechyMa podobną koncepcję, ale mniej rozwlekłe IMO :)
źródło
Jeśli chcesz uniknąć implikacji w scala.collection.JavaConversions , możesz użyć scala.collection.JavaConverters do jawnej konwersji.
Zwróć uwagę na użycie
asScala
metody do konwersji JavaIterator
do ScalaIterator
.JavaConverters są dostępne od wersji Scala 2.8.1.
źródło
import scala.collection.JavaConverters._
a potemjavaList.iterator().asScala
z twojego przykładu i zadziałało