Java中有限生成的流 – 如何创建一个?

在Java中,可以使用Stream.generate(supplier)轻松生成无限流。 但是,我需要生成一个最终完成的流。

想象一下,例如,我想要一个目录中所有文件的流。 文件数量可能很大,因此我无法预先收集所有数据并从中创建流(通过collection.stream() )。 我需要一块一块地生成序列。 但是流显然会在某个时刻完成,而终端运营商(如( collect()findAny() )需要对其进行处理,因此Stream.generate(supplier)不适合这里。

有没有合理的简单方法在Java中执行此操作,而不是自己实现整个Stream接口?

我可以想到一个简单的黑客 – 使用无限的Stream.generate(supplier)执行它,并在获取所有实际值时提供null或抛出exception。 但它会破坏标准的流操作符,我只能将它用于我自己的运算符,这些运算符都知道这种行为。

澄清

评论中的人提议我takeWhile()运算符。 这不是我的意思。 如何更好地表达问题…我不是在问如何过滤(或限制)现有的流,我问如何动态创建(生成)流,而不是预先加载所有元素,但是流会有有限的尺寸(事先未知)。

我正在寻找的代码是

  Iterator it = myCustomIteratorThatGeneratesTheSequence(); StreamSupport.stream(Spliterators.spliteratorUnknownSize(it, Spliterator.DISTINCT), false); 

我只是研究了java.nio.file.Files ,如何实现list(path)方法。

有没有合理的简单方法在Java中执行此操作,而不是自己实现整个Stream接口?

一个简单的.limit()保证它将终止。 但这并不总是足够强大。

Stream工厂方法之后,创建海关流源而不重新实现流处理管道的最简单方法是java.util.stream.StreamSupport.stream(Supplier>, int, boolean) java.util.Spliterators.AbstractSpliterator并将其传递给java.util.stream.StreamSupport.stream(Supplier>, int, boolean)

如果您打算使用并行流,请注意AbstractSpliterator仅产生次优分割。 如果您可以更好地控制源, Spliterator可以更好地实现Spliterator接口。

例如,以下代码段将创建一个提供无限序列1,2,3的流…

在该特定示例中,您可以使用IntStream.range()

但是流显然会在某个时刻完成,终端运营商(如(collect()或findAny())需要对其进行处理。

findAny()这样的短路操作实际上可以在无限流上完成,只要有任何匹配的元素。

Java 9引入了Stream.iterate来为一些简单的情况生成有限流。