Finite generated Stream in Java - how to create one?(Java中的有限生成流-如何创建一个?)
问题描述
在 Java 中,可以使用 Stream.generate(supplier)
轻松生成无限流.但是,我需要生成一个最终会完成的流.
In Java, one can easily generate an infinite stream with Stream.generate(supplier)
. However, I would need to generate a stream that will eventually finish.
例如,想象一下,我想要一个目录中所有文件的流.文件的数量可能很大,因此我无法预先收集所有数据并从中创建一个流(通过 collection.stream()
).我需要逐个生成序列.但是流显然会在某个时候结束,并且像 (collect()
或 findAny()
) 这样的终端操作符需要处理它,所以 Stream.generate(供应商)
这里不适合.
Imagine, for example, I want a stream of all files in a directory. The number of files can be huge, therefore I can not gather all the data upfront and create a stream from them (via collection.stream()
). I need to generate the sequence piece by piece. But the stream will obviously finish at some point, and terminal operators like (collect()
or findAny()
) need to work on it, so Stream.generate(supplier)
is not suitable here.
在 Java 中是否有任何合理的简单方法可以做到这一点,而无需我自己实现整个 Stream 接口?
Is there any reasonable easy way to do this in Java, without implementing the entire Stream interface on my own?
我可以想到一个简单的 hack - 使用无限的 Stream.generate(supplier)
来实现,并在获取所有实际值时提供 null 或抛出异常.但它会破坏标准的流操作符,我只能将它与我自己知道这种行为的操作符一起使用.
I can think of a simple hack - doing it with infinite Stream.generate(supplier)
, and providing null or throwing an exception when all the actual values are taken. But it would break the standard stream operators, I could use it only with my own operators that are aware of this behaviour.
澄清
评论中的人建议我使用 takeWhile()
运算符.这不是我的意思.如何更好地表达这个问题......我不是在问如何过滤(或限制)现有的流,我是在问如何动态地创建(生成)流,无需预先加载所有元素,但流会有有限大小(事先未知).
People in the comments are proposing me takeWhile()
operator. This is not what I meant. How to phrase the question better... I am not asking how to filter (or limit) an existing stream, I am asking how to create (generate) the stream - dynamically, without loading all the elements upfront, but the stream would have a finite size (unknown in advance).
解决方案
我要找的代码是
Iterator it = myCustomIteratorThatGeneratesTheSequence();
StreamSupport.stream(Spliterators.spliteratorUnknownSize(it, Spliterator.DISTINCT), false);
我刚刚研究了java.nio.file.Files
,list(path)
方法是如何实现的.
I just looked into java.nio.file.Files
, how the list(path)
method is implemented.
推荐答案
在 Java 中是否有任何合理的简单方法可以做到这一点,而无需我自己实现整个 Stream 接口?
Is there any reasonable easy way to do this in Java, without implementing the entire Stream interface on my own?
一个简单的 .limit()
保证它会终止.但这并不总是足够强大.
A simple .limit()
guarantees that it will terminate. But that's not always powerful enough.
在 Stream
工厂方法之后,在不重新实现流处理管道的情况下创建自定义流源的最简单方法是继承 java.util.Spliterators.AbstractSpliterator
并传递它到 java.util.stream.StreamSupport.stream(Supplier extends Spliterator
After the Stream
factory methods the simplest approach for creating customs stream sources without reimplementing the stream processing pipeline is subclassing java.util.Spliterators.AbstractSpliterator<T>
and passing it to java.util.stream.StreamSupport.stream(Supplier<? extends Spliterator<T>>, int, boolean)
如果您打算使用并行流,请注意 AbstractSpliterator
只会产生次优拆分.如果您对源代码有更多的控制权,那么完全实现 Spliterator
接口会更好.
If you're intending to use parallel streams note that AbstractSpliterator
only yields suboptimal splitting. If you have more control over your source fully implementing the Spliterator
interface can better.
例如,以下代码段将创建一个 Stream 提供无限序列 1,2,3...
For example, the following snippet would create a Stream providing an infinite sequence 1,2,3...
在该特定示例中,您可以使用 IntStream.range()
in that particular example you could use IntStream.range()
但是流显然会在某个时候结束,像 (collect() 或 findAny()) 这样的终端操作符需要处理它.
But the stream will obviously finish at some point, and terminal operators like (collect() or findAny()) need to work on it.
像 findAny()
这样的短路操作实际上可以在无限流上完成,只要有任何匹配的元素.
short-circuiting operations like findAny()
can actually finish on an infinite stream, as long as there is any element that matches.
Java 9 引入 Stream.iterate 为一些简单的情况生成有限流.
Java 9 introduces Stream.iterate to generate finite streams for some simple cases.
这篇关于Java中的有限生成流-如何创建一个?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:Java中的有限生成流-如何创建一个?
基础教程推荐
- 如何对 HashSet 进行排序? 2022-01-01
- Java 中保存最后 N 个元素的大小受限队列 2022-01-01
- 如何使用 Eclipse 检查调试符号状态? 2022-01-01
- Spring Boot Freemarker从2.2.0升级失败 2022-01-01
- 首次使用 Hadoop,MapReduce Job 不运行 Reduce Phase 2022-01-01
- 如何强制对超级方法进行多态调用? 2022-01-01
- 如何在不安装整个 WTP 包的情况下将 Tomcat 8 添加到 Eclipse Kepler 2022-01-01
- 由于对所需库 rt.jar 的限制,对类的访问限制? 2022-01-01
- 在螺旋中写一个字符串 2022-01-01
- 如何使用 Stream 在集合中拆分奇数和偶数以及两者的总和 2022-01-01