我想知道何时创建自己的无限流以及Stream.generate
标准库中的流如何停止...
例如,当您有一个包含记录的列表时:
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/)。
第二个问题是:如何用Stream.generate
相同的方式停止使用创建的流?
有限流根本不是通过创建的Stream.generate
。
实现数据流的标准方法,是实现Spliterator
,有时使用的Iterator
弯路。在这两种情况下,实现都有一种方法来报告结束,例如,当Spliterator.tryAdvance
returnfalse
或其forEachRemaining
方法刚刚返回时,或者在Iterator
源的情况下,当hasNext()
return时false
。
ASpliterator
甚至可以在处理开始之前报告预期的元素数量。
通过Stream
接口内部的一种工厂方法创建的流,Stream.generate
也可以通过Spliterator
流实现或使用流实现的内部功能来实现,但是无论如何实现,都无法实现更改其行为,因此使此类流有限的唯一方法是将limit
操作链接到该流。
如果要创建不由数组或集合支持的非空有限流,并且现有的流源都不适合,则必须实现自己的流Spliterator
并从中创建流。如上所述,您可以使用现有方法从中创建Spliterator
out Iterator
,但是您应该避免使用Iterator
just的诱惑是因为它很熟悉。一个Spliterator
并不难实现:
/** 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);
}
从这个起点开始,您可以添加接口default
方法的替代Spliterator
,权衡开发费用和潜在的性能改进,例如
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);
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句