我正在编写一些使用Apache POI API的Scala代码 . 我想迭代我从Sheet类得到的 java.util.Iterator
中包含的行 . 我想在 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)
}
}
}
9 回答
有一个包装类(
scala.collection.jcl.MutableIterator.Wrapper
) . 所以,如果你定义然后它将充当Scala迭代器的子类,因此您可以执行
foreach
.从Scala 2.8开始,您所要做的就是导入JavaConversions对象,该对象已经声明了适当的转换 .
但这在以前的版本中不起作用 .
这里的正确答案是定义从Java的
Iterator
到某些自定义类型的隐式转换 . 此类型应实现foreach
方法,该方法委托给底层Iterator
. 这将允许您将Scalafor
-loop与任何JavaIterator
一起使用 .Scala 2.12.0弃用
scala.collection.JavaConversions
,所以从2.12.0开始,这样做的方法如下:(注意导入,new是JavaConverters,不推荐使用JavaConversions)
对于Scala 2.10:
使用Scala 2.10.4(可能更早),可以通过导入scala.collection.JavaConversions.asScalaIterator将java.util.Iterator [A]隐式转换为scala.collection.Iterator [A] . 这是一个例子:
您可以将Java集合转换为数组并使用它:
或者继续将数组转换为Scala列表:
如果要遍历大型数据集,那么您可能不希望使用
.asScala
隐式转换将整个集合加载到内存中 . 在这种情况下,一种方便的方法是实现scala.collection.Iterator
特征它有类似的概念但不那么冗长的IMO :)
如果您想避免scala.collection.JavaConversions中的implicits,您可以使用 scala.collection.JavaConverters 显式转换 .
请注意使用
asScala
方法将JavaIterator
转换为ScalaIterator
.自Scala 2.8.1以来,JavaConverters一直可用 .