如何将一个迭代器转换为一个stream?
我正在寻找一种简洁的方式来将Iterator
转换为Stream
或者更具体地说,将迭代器“查看”为stream。
出于性能的原因,我想避免在新列表中的迭代器的副本:
Iterator<String> sourceIterator = Arrays.asList("A", "B", "C").iterator(); Collection<String> copyList = new ArrayList<String>(); sourceIterator.forEachRemaining(copyList::add); Stream<String> targetStream = copyList.stream();
根据评论中的一些build议,我也尝试使用Stream.generate
:
public static void main(String[] args) throws Exception { Iterator<String> sourceIterator = Arrays.asList("A", "B", "C").iterator(); Stream<String> targetStream = Stream.generate(sourceIterator::next); targetStream.forEach(System.out::println); }
但是,我得到一个NoSuchElementException
(因为没有调用hasNext
)
Exception in thread "main" java.util.NoSuchElementException at java.util.AbstractList$Itr.next(AbstractList.java:364) at Main$$Lambda$1/1175962212.get(Unknown Source) at java.util.stream.StreamSpliterators$InfiniteSupplyingSpliterator$OfRef.tryAdvance(StreamSpliterators.java:1351) at java.util.Spliterator.forEachRemaining(Spliterator.java:326) at java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:580) at Main.main(Main.java:20)
我曾看过StreamSupport
和Collections
但是我没有find任何东西。
一种方法是从迭代器创build一个Spliterator,并将其用作stream的基础:
Iterator<String> sourceIterator = Arrays.asList("A", "B", "C").iterator(); Stream<String> targetStream = StreamSupport.stream( Spliterators.spliteratorUnknownSize(sourceIterator, Spliterator.ORDERED), false);
另一种更具可读性的方法是使用Iterable – 并且从Iterator创buildIterable对于lambdaexpression式非常简单,因为Iterable是一个function性接口:
Iterator<String> sourceIterator = Arrays.asList("A", "B", "C").iterator(); Iterable<String> iterable = () -> sourceIterator; Stream<String> targetStream = StreamSupport.stream(iterable.spliterator(), false);
伟大的build议! 这是我可重复使用的:
public class StreamUtils { public static <T> Stream<T> asStream(Iterator<T> sourceIterator) { return asStream(sourceIterator, false); } public static <T> Stream<T> asStream(Iterator<T> sourceIterator, boolean parallel) { Iterable<T> iterable = () -> sourceIterator; return StreamSupport.stream(iterable.spliterator(), parallel); } }
和用法(确保静态导入asStream):
List<String> aPrefixedStrings = asStream(sourceIterator) .filter(t -> t.startsWith("A")) .collect(toList());
自21版以来,番石榴图书馆提供
Streams.stream(iterator)
它做@assylias答案显示。
使用Spliterator
从Iterator
创buildSpliterator
类包含多个用于创buildspliterator的函数,例如,在这里使用的是将迭代器作为参数的StreamSupport
,然后使用StreamSupport
创buildStream
Spliterator<Model> spliterator = Spliterators.spliteratorUnknownSize( iterator, Spliterator.NONNULL); Stream<Model> stream = StreamSupport.stream(spliterator, false);
您可以使用迭代器简单地使用限制函数:
Stream.generate(iterator::next).limit(list.size())