Java中有限生成的流 - 如何创建一个? [英] Finite generated Stream in Java - how to create one?

查看:186
本文介绍了Java中有限生成的流 - 如何创建一个?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Java中,可以使用 Stream.generate(supplier)轻松生成无限流。但是,我需要生成一个最终完成的流。



想象一下,例如,我想要一个目录中所有文件的流。文件数量可能很大,因此我无法预先收集所有数据并从中创建流(通过 collection.stream())。我需要一块一块地生成序列。但是流显然会在某个时刻完成,终端运营商需要( collect() findAny())要处理它,所以 Stream.generate(供应商)不适合这里。



有没有合理的容易在Java中实现这一点的方法,而不是我自己实现整个Stream接口?



我能想到一个简单的黑客 - 用无限的来实现它Stream.generate(supplier),并在获取所有实际值时提供null或抛出异常。但它会打破标准的流操作符,我只能将它用于我自己的操作符,这些操作符都知道这种行为。



澄清



评论中的人提议我 takeWhile()运算符。这不是我的意思。如何更好地表达问题...我不是在问如何过滤(或限制)现有的流,我问如何动态创建(生成)流,而不是预先加载所有元素,但是流会有有限大小(提前未知)。



解决方案



代码I正在寻找是

  Iterator it = myCustomIteratorThatGeneratesTheSequence(); 
StreamSupport.stream(Spliterators.spliteratorUnknownSize(it,Spliterator.DISTINCT),false);

我刚看了 java.nio.file.Files ,如何实现列表(路径)方法。

解决方案

< blockquote>

有没有合理的简单方法在Java中实现这一点,而不是自己实现整个Stream接口?


一个简单的 .limit()保证它将终止。但这并不总是足够强大。



Stream 工厂方法之后,最简单的方法是创建海关流源而无需重新实现流处理管道正在继承 java.util.Spliterators.AbstractSpliterator< T> 并将其传递给 java.util.stream.StreamSupport.stream(Supplier< ;?extends Spliterator< T>>,int,boolean)



如果您打算使用并行流,请注意 AbstractSpliterator 仅产生次优分割。如果您对源代码有更多控制权,可以更好地实现 Spliterator 界面。


例如,以下代码段将创建一个Stream,在该特定示例中提供无限序列1,2,3 ......


你可以使用 IntStream.range()


但是这个流显然会在有一点,终端运营商喜欢(collect()或findAny())需要对它进行处理。


短路操作如 findAny()实际上可以在无限流上完成,只要有任何匹配的元素。



Java 9介绍 Stream.iterate 为一些简单的案例生成有限流。


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.

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.

Is there any reasonable easy way to do this in Java, without implementing the entire Stream interface on my own?

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.

CLARIFICATION

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).

SOLUTION

The code I was looking for is

    Iterator it = myCustomIteratorThatGeneratesTheSequence();
    StreamSupport.stream(Spliterators.spliteratorUnknownSize(it, Spliterator.DISTINCT), false);

I just looked into java.nio.file.Files, how the list(path) method is implemented.

解决方案

Is there any reasonable easy way to do this in Java, without implementing the entire Stream interface on my own?

A simple .limit() guarantees that it will terminate. But that's not always powerful enough.

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)

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.

For example, the following snippet would create a Stream providing an infinite sequence 1,2,3...

in that particular example you could use IntStream.range()

But the stream will obviously finish at some point, and terminal operators like (collect() or findAny()) need to work on it.

short-circuiting operations like findAny() can actually finish on an infinite stream, as long as there is any element that matches.

Java 9 introduces Stream.iterate to generate finite streams for some simple cases.

这篇关于Java中有限生成的流 - 如何创建一个?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆