流如何停止? [英] How do streams stop?
问题描述
我想知道当我使用 Stream.generate
创建自己的无限流时,标准库中的流如何停止...
I was wondering when I created my own infinite stream with Stream.generate
how the Streams which are in the standard library stop...
例如,当您有一个包含记录的列表时:
For example when you have a list with records:
List<Record> records = getListWithRecords();
records.stream().forEach(/* do something */);
流不会是无限的并且永远运行,但是当遍历列表中的所有项目时它会停止.但这是如何工作的?相同的功能适用于 Files.lines(path)
创建的流(来源:http://www.mkyong.com/java8/java-8-stream-read-a-file-line-by-line/).
The stream won't be infinite and running forever, but it will stop when all items in the list are traversed. But how does that work? The same functionality applies for the stream created by Files.lines(path)
(source: http://www.mkyong.com/java8/java-8-stream-read-a-file-line-by-line/).
第二个问题,如何以同样的方式停止使用 Stream.generate
创建的流?
And a second question, how can a stream created with Stream.generate
be stopped in the same manner then?
推荐答案
有限流根本不是通过 Stream.generate
创建的.
Finite streams simply aren’t created via Stream.generate
.
实现流的标准方法是实现 Spliterator
,有时使用 Iterator
绕道.在任何一种情况下,实现都有一种方法来报告结束,例如当 Spliterator.tryAdvance
返回 false
或其 forEachRemaining
方法仅返回时,或者在 Iterator
源的情况下,当hasNext()
返回 false
.
The standard way of implementing a stream, is to implement a Spliterator
, sometimes using the Iterator
detour. In either case, the implementation has a way to report an end, e.g. when Spliterator.tryAdvance
returns false
or its forEachRemaining
method just returns, or in case of an Iterator
source, when hasNext()
returns false
.
Spliterator
甚至可以在处理开始之前报告预期的元素数量.
A Spliterator
may even report the expected number of elements before the processing begins.
Streams,通过 Stream
接口内的一种工厂方法创建,例如 Stream.generate
可以由 Spliterator
实现也可以使用流实现的内部功能,但无论它们是如何实现的,您都无法通过此实现来改变它们的行为,因此使这种流有限的唯一方法是链接 限制
对流的操作.
Streams, created via one of the factory methods inside the Stream
interface, like Stream.generate
may be implemented either, by a Spliterator
as well or using internal features of the stream implementation, but regardless of how they are implemented, you don’t get hands on this implementation to change their behavior, so the only way to make such a stream finite, is to chain a limit
operation to the stream.
如果你想创建一个非空的有限流,它不受数组或集合的支持,并且现有的流源都不适合,你必须实现自己的 Spliterator
和 从中创建一个流一个>.如上所述,您可以使用现有方法从 Iterator
中创建 Spliterator
,但您应该抵制使用 Iterator
的诱惑只是因为熟悉.Spliterator
并不难实现:
If you want to create a non-empty finite stream that is not backed by an array or collection and none of the existing stream sources fits, you have to implement your own Spliterator
and create a stream out of it. As told above, you can use an existing method to create a Spliterator
out of an Iterator
, but you should resists the temptation to use an Iterator
just because it’s familiar. A Spliterator
is not hard to implement:
/** like {@code Stream.generate}, but with an intrinsic limit */
static <T> Stream<T> generate(Supplier<T> s, long count) {
return StreamSupport.stream(
new Spliterators.AbstractSpliterator<T>(count, Spliterator.SIZED) {
long remaining=count;
public boolean tryAdvance(Consumer<? super T> action) {
if(remaining<=0) return false;
remaining--;
action.accept(s.get());
return true;
}
}, false);
}
从这个起点,您可以为 Spliterator
接口的 default
方法添加覆盖,权衡开发费用和潜在的性能改进,例如
From this starting point, you can add overrides for the default
methods of the Spliterator
interface, weighting development expense and potential performance improvements, e.g.
static <T> Stream<T> generate(Supplier<T> s, long count) {
return StreamSupport.stream(
new Spliterators.AbstractSpliterator<T>(count, Spliterator.SIZED) {
long remaining=count;
public boolean tryAdvance(Consumer<? super T> action) {
if(remaining<=0) return false;
remaining--;
action.accept(s.get());
return true;
}
/** May improve the performance of most non-short-circuiting operations */
@Override
public void forEachRemaining(Consumer<? super T> action) {
long toGo=remaining;
remaining=0;
for(; toGo>0; toGo--) action.accept(s.get());
}
}, false);
}
这篇关于流如何停止?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!