如何从迭代器创建Java 8流?
是否可以从迭代器创建一个Stream,其中对象序列与通过重复调用迭代器的next()方法生成的对象序列相同? 我正在考虑的具体情况涉及使用TreeSet.descendingIterator()返回的迭代器,但我可以想象其他情况下迭代器,而不是它引用的集合是可用的。
例如,对于TreeSet tset
我们可以编写tset.stream()...
并以集合的排序顺序获取该集合中的对象流,但是如果我们希望它们以不同的顺序,例如可以通过使用descendingIterator()
吗? 我想像tset.descendingIterator().stream()...
或stream( tset.descendingIterator() )...
,虽然这些forms都不是有效的。
对于NavigableSet.descendingIterator()
的特定示例,我认为最简单的方法是使用NavigableSet.descendingSet()
。
但鉴于您可能对更一般的情况感兴趣,以下似乎有效:
import java.util.Iterator; import java.util.Spliterator; import java.util.Spliterators; import java.util.TreeSet; import java.util.stream.Stream; import java.util.stream.StreamSupport; public class Streams { public static void main(String... args) { TreeSet set = new TreeSet<>(); set.add("C"); set.add("A"); set.add("B"); Iterator iterator = set.descendingIterator(); int characteristics = Spliterator.DISTINCT | Spliterator.SORTED | Spliterator.ORDERED; Spliterator spliterator = Spliterators.spliteratorUnknownSize(iterator, characteristics); boolean parallel = false; Stream stream = StreamSupport.stream(spliterator, parallel); stream.forEach(System.out::println); // prints C, then B, then A } }
简而言之,您必须首先使用Spliterator
中的一种静态方法从Iterator
创建Spliterators
。 然后,您可以使用StreamSupport
的静态方法创建Stream
。
我手动创建Spliterators和Streams没有那么多经验,所以我无法评论它们的特征应该是什么或它们会产生什么样的影响。 在这个特别简单的例子中,我是否定义了上述特征,或者我是否将其设置为0(即没有特征)似乎并不重要。 Spliterators
还有一个方法用于创建具有初始大小估计的Spliterator – 我想在这个特定的例子中你可以使用set.size()
,但是如果你想处理任意迭代器,我想这不会是这种情况。 同样,我不太确定它对性能的影响。
static Stream iteratorToFiniteStream(final Iterator iterator) { return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, 0), false); } static Stream iteratorToInfiniteStream(final Iterator iterator) { return Stream.generate(iterator::next); }
这不会创建流,但Iterator
也有一个名为forEachRemaining
的方法:
someIterator.forEachRemaining(System.out::println); someIterator.forEachRemaining(s -> s.doSomething()); //etc.
您传入的参数是Consumer ,它与您传递给Stream :: forEach的内容相同 。
以下是该方法的文档 。 请注意, 您不能像流一样继续使用“链” 。 但我仍然发现这很有用,我想要一个Iterator的Stream。