Spliterator与Stream.Builder

问题描述 投票:7回答:2

我读了一些关于如何创建有限StreamFinite generated Stream in Java - how to create one?How do streams stop?)的问题。

答案建议实施SpliteratorSpliterator将实现逻辑如何以及下一个提供的元素(tryAdvance)。但是还有另外两种非默认方法trySplitestimateSize(),我必须实现它们。

Spliterator的JavaDoc说:

用于遍历和分区源元素的对象。 Spliterator覆盖的元素源可以是例如阵列,Collection,IO通道或生成器函数。 ... Spliterator API旨在支持有效的并行遍历以及顺序遍历,支持分解以及单元素迭代。 ...

另一方面,我可以实现逻辑如何前进到围绕Stream.Builder的下一个元素并绕过Spliterator。在每次推进时,我都会称acceptadd,最后是build。所以它看起来很简单。

JavaDoc说什么?

Stream的可变建设者。这允许通过单独生成元素并将它们添加到Stream来创建Builder(没有使用ArrayList作为临时缓冲区的复制开销。)

使用StreamSupport.stream我可以使用Spliterator来获得Stream。还有一个Builder将提供Stream

什么时候应该/我可以使用Stream.Builder? 只有当Spliterator效率不高时(例如因为无法对源进行分区并且无法估计其大小)?

java java-8 java-stream builder spliterator
2个回答
7
投票

请注意,您可以扩展Spliterators.AbstractSpliterator。然后,只有tryAdvance来实现。

因此,实施Spliterator的复杂性并不高。

根本区别在于,只有在需要新元素时才会调用SpliteratortryAdvance方法。相比之下,Stream.Builder有一个存储空间,它将填充所有流元素,然后才能获得Stream。

因此,Spliterator是各种惰性求值的首选,也是您想要遍历的现有存储的首选,以避免复制数据。

当元素的创建是非均匀的时,构建器是第一选择,因此您无法按需创建元素。想想你否则会使用Stream.of(…)的情况,但事实证明它是不灵活的。

例如。你有Stream.of(a, b, c, d, e),但现在事实证明,cd是可选的。所以解决方案是

Stream.Builder<MyType> builder = Stream.builder();
builder.add(a).add(b);
if(someCondition) builder.add(c).add(d);
builder.add(e).build()
   /* stream operations */

其他用例是this answer,其中需要Consumer来查询现有的分裂器,然后将值推回到Stream,或者this answer,其中没有随机访问的结构(类层次结构)应该以相反的顺序流式传输。


3
投票

另一方面,我可以实现逻辑如何前进到Stream.Builder周围的下一个元素并绕过Spliterator。在每次推进时,我都会称acceptadd,最后是build。所以它看起来很简单。

是的,不是。这很简单,但我认为您不了解使用模式:

流构建器具有生命周期,该生命周期从构建阶段开始,在此期间可以添加元素,然后转换到构建阶段,之后可能不会添加元素。构建的阶段在调用build()方法时开始,该方法创建一个有序的Stream,其元素是添加到流构建器的元素,按添加顺序排列。

(Qazxswpoi)

特别是不,你不会在任何流前进上调用JavadocsStream.Builderaccept方法。您需要提前为流提供所有对象。然后你add得到一个流,它将提供你之前添加的所有对象。这类似于将所有对象添加到build(),然后调用ListList方法。

如果这符合您的目的,您实际上可以有效地做到这一点,那就太好了!但是如果你需要根据需要生成元素,无论是否有限制,那么stream()无法帮助你。 Stream.Builder可以。

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.