我正在编写一些使用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)
}
}
}
答案 0 :(得分:250)
从Scala 2.8开始,您所要做的就是导入JavaConversions对象,该对象已经声明了相应的转换。
import scala.collection.JavaConversions._
但这在以前的版本中不起作用。
答案 1 :(得分:25)
有一个包装类(scala.collection.jcl.MutableIterator.Wrapper
)。所以,如果你定义
implicit def javaIteratorToScalaIterator[A](it : java.util.Iterator[A]) = new Wrapper(it)
然后它将充当Scala迭代器的子类,因此您可以执行foreach
。
答案 2 :(得分:16)
Scala 2.12.0弃用了 @Override
public List<WorkItem> getWorkItem() {
final String url = "http://10.0.2.2:8080/items/all/items";
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(Request.Method.GET, url, null, new Response.Listener<JSONArray>() {
@Override
public void onResponse(JSONArray response) {
Log.d("Response", response.toString());
try {
arrayList = new ArrayList<>();
response = new JSONArray(response.toString());
for (int i = 0; i < response.length(); i++) {
JSONObject jsonobject = response.getJSONObject(i);
String title = jsonobject.getString("title");
String description = jsonobject.getString("description");
String state = jsonobject.getString("status");
String assignee = jsonobject.getString("assignee");
arrayList.add(new WorkItem(title, description, state, assignee));
arrayList.size();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.d("Error", error.getMessage());
}
});
jsonArrayRequest.setTag(REQUEST_TAG);
mQueue.add(jsonArrayRequest);
return arrayList;
}
,所以从2.12.0开始,这样做的方法就是:
scala.collection.JavaConversions
(注意导入,new是JavaConverters,不推荐使用JavaConversions)
答案 3 :(得分:15)
这里的正确答案是定义从Java Iterator
到某些自定义类型的隐式转换。此类型应实现foreach
方法,该方法委托给基础Iterator
。这将允许您使用Scala for
- 循环与任何Java Iterator
。
答案 4 :(得分:9)
对于Scala 2.10:
// Feature warning if you don't enable implicit conversions...
import scala.language.implicitConversions
import scala.collection.convert.WrapAsScala.enumerationAsScalaIterator
答案 5 :(得分:5)
使用Scala 2.10.4+(可能更早),可以通过导入scala.collection.JavaConversions.asScalaIterator将java.util.Iterator [A]隐式转换为scala.collection.Iterator [A]。这是一个例子:
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
}
}
答案 6 :(得分:4)
您可以将Java集合转换为数组并使用它:
val array = java.util.Arrays.asList("one","two","three").toArray
array.foreach(println)
或继续将数组转换为Scala列表:
val list = List.fromArray(array)
答案 7 :(得分:3)
如果您正在迭代大型数据集,那么您可能不希望通过scala.collection.Iterator
隐式转换将整个集合加载到内存中。在这种情况下,一种方便的方法是实现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
特征
SerialPort.writeInt(KeyEvent.VK_CONTROL + KeyEvent.VK_P);
它有类似的概念但不那么详细的IMO:)
答案 8 :(得分:2)
如果您想避免 scala.collection.JavaConversions 中的含义,可以使用 scala.collection.JavaConverters 进行显式转换。
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
请注意使用asScala
方法将Java Iterator
转换为Scala Iterator
。
自Scala 2.8.1以来,JavaConverters已经可用。