在Java中,可以使用Stream.generate(supplier)
轻松生成无限流。但是,我需要生成一个最终会结束的流。
比如说,我想要一个文件夹中所有文件的流。文件数量可能很大,因此我无法预先收集所有数据并从它们创建流(通过collection.stream()
)。我需要逐个生成序列。但是这个流显然会在某个时候结束,并且像collect()
或findAny()
这样的终端操作符需要对其进行操作,因此Stream.generate(supplier)
在这里不适用。
有没有什么合理简单的方法在Java中实现这一点,而无需自己实现整个Stream接口?
我可以想到一个简单的技巧-使用无限的Stream.generate(supplier)
来做,当所有实际值被取走时提供null或抛出异常。但这将破坏标准流算子,我只能使用自己的算子,让它们知道这种行为。
澄清
评论中的人建议我使用takeWhile()
运算符。这不是我的意思。如何更好地表达问题...我不是在问如何过滤(或限制)现有的流,而是在问如何创建(生成)流-动态地,无需预先加载所有元素,但流将具有有限的大小(事先未知)。
解决方案
我正在寻找的代码是
Iterator it = myCustomIteratorThatGeneratesTheSequence();
StreamSupport.stream(Spliterators.spliteratorUnknownSize(it, Spliterator.DISTINCT), false);
我刚才查看了java.nio.file.Files
,看一下list(path)
方法是如何实现的。
openjdk 9
提供了takeWhile()
。 - Andrew Tobilko,然后使用这个答案https://dev59.com/-WAf5IYBdhLWcg3wlDUD#24511534将
Iterator转换为
Stream`。这样,迭代器只会在内存中保留少量文件,并且流将被惰性地评估。虽然这很麻烦。 - Paul BoddingtonSpliterator
的逻辑是否更合适,然后再决定是否实现一个更复杂的Iterator
并将其包装在一个Spliterator
中。可以参考这个答案作为示例。 - Holger