我正在使用库(JXPath)来查询bean的图形,以便提取匹配的元素。但是,JXPath返回匹配元素组作为java.lang.Iterator的实例,我更愿意将其转换为不可变的scala列表。有没有比在迭代器上迭代并在每个迭代步骤创建一个新的不可变列表更简单的方法?
答案 0 :(得分:32)
您可能想重新考虑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
方法,但(正如Daniel指出的那样)有一个toIndexedSeq
方法会返回Vector
作为默认的IndexedSeq
子类(就像List
一样是默认的Seq
)。
javaIterator.asScala.toIndexedSeq
答案 1 :(得分:8)
编辑:您应该查看Kevin Wright's answer,它提供了自Scala 2.8.1以来可用的更好的解决方案,具有更少的隐含魔力。
您可以从scala.collection.JavaConversions
导入隐式转化,然后无缝地创建新的Scala集合,例如像这样:
import collection.JavaConversions._
println(List() ++ javaIterator)
您的Java迭代器由JavaConversions.asScalaIterator
转换为Scala迭代器。具有类型A
的元素的Scala迭代器实现TraversableOnce[A]
,这是将集合与++
连接所需的参数类型。
如果您需要其他收藏类型,只需将List()
更改为您需要的内容(例如IndexedSeq()
或collection.mutable.Seq()
等)。