从java.lang.Iterator创建一个不可变列表

时间:2011-05-16 08:40:18

标签: scala scala-collections scala-java-interop jxpath

我正在使用库(JXPath)来查询bean的图形,以便提取匹配的元素。但是,JXPath返回匹配元素组作为java.lang.Iterator的实例,我更愿意将其转换为不可变的scala列表。有没有比在迭代器上迭代并在每个迭代步骤创建一个新的不可变列表更简单的方法?

2 个答案:

答案 0 :(得分:32)

您可能想重新考虑List的需求,虽然从Java开始时感觉非常熟悉,而List是不可变Seq的默认实现,但它通常不是最好的选择收藏。

列表最适合的操作是那些已经通过迭代器可用的操作(基本上采用连续的头元素和前置元素)。如果迭代器还没有给你你需要的东西,那么我几乎可以保证List不会是你最好的选择 - 矢量会更合适。


完成了这项工作......在Java和Scala集合之间进行转换的推荐技术(自Scala 2.8.1起)是通过scala.collection.JavaConverters。这为您提供了比JavaConversions更多的控制,并避免了一些可能的隐式冲突。

您不会以这种方式进行直接隐式转换。相反,您会将asScalaasJava方法移植到集合上,从而允许您明确执行转换。

将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()等)。