scala 从 java.lang.Iterator 创建一个不可变列表
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6014881/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Create an immutable list from a java.lang.Iterator
提问by Romain Rouvoy
I'm using a library (JXPath) to query a graph of beans in order to extract matching elements. However, JXPath returns groups of matching elements as an instance of java.lang.Iterator and I'd rather like to convert it into an immutable scala list. Is there any simpler way of doing than iterating over the iterator and creating a new immutable list at each iteration step ?
我正在使用一个库 ( JXPath) 来查询 bean 图形以提取匹配的元素。但是,JXPath 将匹配元素组作为 java.lang.Iterator 的实例返回,我更愿意将其转换为不可变的 scala 列表。有没有比迭代迭代器并在每个迭代步骤创建一个新的不可变列表更简单的方法?
回答by Kevin Wright
You might want to rethink the need for a List, although it feels very familiar when coming from Java, and List is the default implementation of an immutable Seq, it often isn't the best choice of collection.
您可能想要重新考虑对 a 的需求List,尽管它来自 Java 时感觉非常熟悉,并且 List 是不可变的默认实现Seq,但它通常不是集合的最佳选择。
The operations that list is optimal for are those already available via an iterator (basically taking consecutive head elements and prepending elements). If an iterator doesn't already give you what you need, then I can pretty much guarantee that a List won't be your best choice - a vector would be more appropriate.
list 最适合的操作是那些已经通过迭代器可用的操作(基本上采用连续的头元素和前置元素)。如果迭代器还没有给你你需要的东西,那么我几乎可以保证 List 不会是你的最佳选择——向量会更合适。
Having got that out the way... The recommended technique to convert between Java and Scala collections (since Scala 2.8.1) is via scala.collection.JavaConverters. This gives you more control than JavaConversionsand avoids some possible implicit conflicts.
解决了这个问题……在 Java 和 Scala 集合之间进行转换的推荐技术(自 Scala 2.8.1 起)是通过scala.collection.JavaConverters. JavaConversions与避免一些可能的隐式冲突相比,这为您提供了更多的控制权。
You won't have a direct implicit conversion this way. Instead, you get asScalaand asJavamethods pimped onto collections, allowing you to perform the conversions explicitly.
您不会以这种方式进行直接的隐式转换。相反,您将 getasScala和asJava方法拉到集合上,允许您显式执行转换。
To convert a Java iterator to a Scala iterator:
要将 Java 迭代器转换为 Scala 迭代器:
javaIterator.asScala
To convert a Java iterator to a Scala List (via the scala iterator):
将 Java 迭代器转换为 Scala 列表(通过 Scala 迭代器):
javaIterator.asScala.toList
You may also want to consider converting toSeqinstead of toList. In the case of iterators, this'll return a Stream- allowing you to retain the lazy behaviour of iterators within the richer Seqinterface.
您可能还想考虑转换toSeq而不是toList. 在迭代器的情况下,这将返回一个Stream- 允许您在更丰富的Seq接口中保留迭代器的惰性行为。
EDIT:There's no toVectormethod, but (as Daniel pointed out) there's a toIndexedSeqmethod that will return a Vectoras the default IndexedSeqsubclass (just as Listis the default Seq).
编辑:没有toVector方法,但是(正如 Daniel 指出的)有一个toIndexedSeq方法将返回 aVector作为默认IndexedSeq子类(就像Listdefault 一样Seq)。
javaIterator.asScala.toIndexedSeq
回答by Jean-Philippe Pellet
EDIT:You should probably look at Kevin Wright's answer, which provides a better solution available since Scala 2.8.1, with less implicit magic.
编辑:您可能应该看看Kevin Wright's answer,它提供了自 Scala 2.8.1 以来可用的更好的解决方案,隐式魔法较少。
You can import the implicit conversions from scala.collection.JavaConversionsand then create a new Scala collection seamlessly, e.g. like this:
您可以从中导入隐式转换scala.collection.JavaConversions,然后无缝地创建一个新的 Scala 集合,例如:
import collection.JavaConversions._
println(List() ++ javaIterator)
Your Java iterator is converted to a Scala iterator by JavaConversions.asScalaIterator. A Scala iterator with elements of type Aimplements TraversableOnce[A], which is the argument type needed to concatenate collections with ++.
您的 Java 迭代器通过JavaConversions.asScalaIterator. 具有类型为Aimplements 的元素的 Scala 迭代器TraversableOnce[A],这是将集合与 连接所需的参数类型++。
If you need another collection type, just change List()to whatever you need (e.g., IndexedSeq()or collection.mutable.Seq(), etc.).
如果您需要其他集合类型,只需更改List()为您需要的任何类型(例如,IndexedSeq()或collection.mutable.Seq()等)。

