【发布时间】:2016-07-03 01:18:54
【问题描述】:
在 Java 中,使用Stream.generate(supplier) 可以轻松生成无限流。但是,我需要生成一个最终会完成的流。
例如,想象一下,我想要一个目录中所有文件的流。文件的数量可能很大,因此我无法预先收集所有数据并从中创建一个流(通过collection.stream())。我需要逐个生成序列。但是流显然会在某个时候结束,并且像(collect() 或findAny())这样的终端操作员需要处理它,所以Stream.generate(supplier) 不适合这里。
在 Java 中是否有任何合理简单的方法可以做到这一点,而无需我自己实现整个 Stream 接口?
我可以想到一个简单的技巧 - 使用无限 Stream.generate(supplier) 进行操作,并在获取所有实际值时提供 null 或抛出异常。但它会破坏标准的流操作符,我只能将它与我自己知道这种行为的操作符一起使用。
澄清
cmets 中的人向我求婚takeWhile() 运营商。这不是我的意思。如何更好地表达这个问题......我不是在问如何过滤(或限制)现有的流,我是在问如何动态地创建(生成)流,无需预先加载所有元素,但流会有有限大小(事先未知)。
解决方案
我要找的代码是
Iterator it = myCustomIteratorThatGeneratesTheSequence();
StreamSupport.stream(Spliterators.spliteratorUnknownSize(it, Spliterator.DISTINCT), false);
我刚刚研究了java.nio.file.Files,list(path) 方法是如何实现的。
【问题讨论】:
-
我想我不明白。您是否正在寻找某种
takeWhile,例如这里的stackoverflow.com/q/20746429/1743880? -
你看过IntStream.range和朋友这样的方法吗?
-
openjdk 9提供takeWhile() -
@JanXMarek 一种方法是使用此答案stackoverflow.com/a/17959135/3973077 创建
Iterator<File>,然后使用此stackoverflow.com/a/24511534/3973077 将Iterator转换为Stream。这样迭代器只会在内存中保存一小堆文件,并且流将被延迟评估。虽然工作量很大。 -
我强烈建议先检查
Spliterator的逻辑是否更合适,然后再执行更复杂的Iterator以将其包装在Spliterator中。有关示例,请参见 this answer...
标签: java java-8 java-stream