【发布时间】:2011-05-16 08:40:18
【问题描述】:
我正在使用一个库 (JXPath) 来查询一个 bean 图,以便提取匹配的元素。但是,JXPath 将匹配元素组作为 java.lang.Iterator 的实例返回,我宁愿将其转换为不可变的 scala 列表。有没有比迭代迭代器并在每个迭代步骤创建一个新的不可变列表更简单的方法?
【问题讨论】:
标签: scala scala-collections scala-java-interop jxpath
我正在使用一个库 (JXPath) 来查询一个 bean 图,以便提取匹配的元素。但是,JXPath 将匹配元素组作为 java.lang.Iterator 的实例返回,我宁愿将其转换为不可变的 scala 列表。有没有比迭代迭代器并在每个迭代步骤创建一个新的不可变列表更简单的方法?
【问题讨论】:
标签: scala scala-collections scala-java-interop jxpath
您可能想重新考虑对List 的需求,尽管它在来自Java 时感觉非常熟悉,并且List 是不可变Seq 的默认实现,但它通常不是集合的最佳选择。
列表最适合的操作是那些已经通过迭代器可用的操作(基本上采用连续的头元素和前置元素)。如果迭代器还没有为您提供所需的东西,那么我几乎可以保证 List 不会是您的最佳选择 - 向量会更合适。
已经解决了...在 Java 和 Scala 集合之间转换的推荐技术(自 Scala 2.8.1 起)是通过 scala.collection.JavaConverters。这比JavaConversions 提供了更多的控制权,并避免了一些可能的隐含冲突。
您不会通过这种方式进行直接隐式转换。相反,您会将 asScala 和 asJava 方法添加到集合中,从而允许您显式执行转换。
将 Java 迭代器转换为 Scala 迭代器:
javaIterator.asScala
将 Java 迭代器转换为 Scala 列表(通过 scala 迭代器):
javaIterator.asScala.toList
您可能还需要考虑转换 toSeq 而不是 toList。对于迭代器,这将返回一个Stream - 允许您在更丰富的Seq 接口中保留迭代器的惰性行为。
编辑:
没有toVector 方法,但是(正如丹尼尔指出的那样)有一个toIndexedSeq 方法将返回一个Vector 作为默认的IndexedSeq 子类(就像List 是默认的Seq)。
javaIterator.asScala.toIndexedSeq
【讨论】:
TraversableOnce 和 ++ 的重要观点;您的回答将帮助一些对连接 Java 集合感兴趣的假设未来读者。
Vector是IndexedSeq的默认实现,还有一个toIndexedSeq。
编辑:您可能应该查看Kevin Wright's answer,它提供了自 Scala 2.8.1 以来可用的更好解决方案,并且隐含的魔法更少。
您可以从scala.collection.JavaConversions 导入隐式转换,然后无缝创建一个新的 Scala 集合,例如像这样:
import collection.JavaConversions._
println(List() ++ javaIterator)
JavaConversions.asScalaIterator 将您的 Java 迭代器转换为 Scala 迭代器。具有 A 类型元素的 Scala 迭代器实现了 TraversableOnce[A],这是将集合与 ++ 连接所需的参数类型。
如果您需要其他集合类型,只需将 List() 更改为您需要的任何内容(例如,IndexedSeq() 或 collection.mutable.Seq() 等)。
【讨论】: