Estou escrevendo um código Scala que usa a API Apache POI . Eu gostaria de iterar sobre as linhas contidas nojava.util.Iterator
que obtenho da classe Folha. Eu gostaria de usar o iterador em um for each
loop de estilo, então estou tentando convertê-lo em uma coleção nativa de Scala, mas não tive sorte.
Eu olhei para as classes / características do wrapper Scala, mas não consigo ver como usá-los corretamente. Como faço para iterar em uma coleção Java no Scala sem usar o verbosewhile(hasNext()) getNext()
estilo de loop?
Aqui está o código que escrevi com base na resposta correta:
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
fonte
fonte
Respostas:
Existe uma classe wrapper (
scala.collection.jcl.MutableIterator.Wrapper
). Então, se você definirem seguida, ele atuará como uma subclasse do iterador Scala para que você possa fazer
foreach
.fonte
A partir do Scala 2.8, tudo o que você precisa fazer é importar o objeto JavaConversions, que já declara as conversões apropriadas.
No entanto, isso não funcionará nas versões anteriores.
fonte
Edit : Scala 2.13.0 está obsoleto
scala.collection.JavaConverters
, então desde 2.13.0 você precisa usarscala.jdk.CollectionConverters
.Scala 2.12.0 está obsoleto
scala.collection.JavaConversions
, portanto, desde 2.12.0, uma maneira de fazer isso seria algo como:(observe a importação, novo é JavaConverters, obsoleto é JavaConversions)
fonte
A resposta correta aqui é definir uma conversão implícita de Java
Iterator
para algum tipo personalizado. Este tipo deve implementar umforeach
método que delega ao subjacenteIterator
. Isso permitirá que você use umfor
loop Scala com qualquer JavaIterator
.fonte
Para Scala 2.10:
fonte
Com Scala 2.10.4+ (e possivelmente anterior), é possível converter implicitamente java.util.Iterator [A] em scala.collection.Iterator [A] importando scala.collection.JavaConversions.asScalaIterator. Aqui está um exemplo:
fonte
Você pode converter a coleção Java em uma matriz e usar isso:
Ou converta a matriz em uma lista Scala:
fonte
Se você estiver iterando por meio de um grande conjunto de dados, provavelmente não deseja carregar a coleção inteira na memória com
.asScala
conversão implícita. Neste caso, uma abordagem de forma prática é implementar oscala.collection.Iterator
traçoTem um conceito semelhante, mas menos prolixo da IMO :)
fonte
Se desejar evitar os implícitos em scala.collection.JavaConversions, você pode usar scala.collection.JavaConverters para converter explicitamente.
Observe o uso do
asScala
método para converter o JavaIterator
em um ScalaIterator
.Os JavaConverters estão disponíveis desde Scala 2.8.1.
fonte
import scala.collection.JavaConverters._
e, em seguida,javaList.iterator().asScala
do seu exemplo e funcionou