如何将一个迭代器转换为一个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) 

我曾看过StreamSupportCollections但是我没有find任何东西。

5 Solutions collect form web for “如何将一个迭代器转换为一个stream?”

一种方法是从迭代器创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答案显示。

使用SpliteratorIterator创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()) 
  • 复制stream以避免“stream已经被操作或closures”(Java 8)
  • 如何确保java8stream中的处理顺序?
  • 我怎样才能从Java 8stream内引发CHECKEDexception? (不包装成未经检查的例外)
  • 用谓词限制stream
  • Java 8 Stream:limit()和skip()之间的区别
  • Java 8:Lambdastream,按exception进行过滤
  • 在Windows XP上安装JDK8 - advapi32.dll错误
  • 如何将Java 8stream转换为数组?
  • lambda表达式在每次执行时都会在堆上创建一个对象吗?
  • 在java中从lambda forEach()返回
  • 你能把一个stream分成两个stream吗?