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 extends Spliterator
java.util.Spliterators.AbstractSpliterator
并将其传递给java.util.stream.StreamSupport.stream(Supplier extends Spliterator
如果您打算使用并行流,请注意AbstractSpliterator
仅产生次优分割。 如果您可以更好地控制源, Spliterator
可以更好地实现Spliterator
接口。
例如,以下代码段将创建一个提供无限序列1,2,3的流…
在该特定示例中,您可以使用IntStream.range()
但是流显然会在某个时刻完成,终端运营商(如(collect()或findAny())需要对其进行处理。
像findAny()
这样的短路操作实际上可以在无限流上完成,只要有任何匹配的元素。
Java 9引入了Stream.iterate来为一些简单的情况生成有限流。