Finite generated Stream in Java – how to create one?,How do streams stop?).
答案建议实施Spliterator. Spliterator将实现逻辑如何以及提供哪个元素作为next(tryAdvance).但是还有另外两种非默认方法trySplit和estimateSize(),我必须实现它们.
Spliterator的JavaDoc说:
An object for traversing and partitioning elements of a source. The source of elements covered by a
Spliterator
could be,for example,an array,aCollection
,an IO channel,or a generator function. … TheSpliterator
API was designed to support efficient parallel
traversal in addition to sequential traversal,by supporting
decomposition as well as single-element iteration. …
另一方面,我可以实现逻辑如何前进到Stream.Builder周围的下一个元素并绕过Spliterator.在每一次进步中,我都会称之为接受或添加,并在最后构建.所以它看起来很简单.
JavaDoc说什么?
A mutable builder for a
Stream
. This allows the creation of aStream
by generating elements individually and adding them to theBuilder
(without the copying overhead that comes from using anArrayList
as a
temporary buffer.)
使用StreamSupport.stream我可以使用Spliterator来获取Stream.而且Builder也会提供Stream.
我应该/什么时候可以使用Stream.Builder?
只有当Spliterator不会更高效时(例如因为无法对源进行分区并且无法估计其大小)?
解决方法
Spliterators.AbstractSpliterator
.然后,只有tryAdvance可以实现.
因此,实现Spliterator的复杂性并不高.
根本区别在于只有在需要新元素时才会调用Spliterator的tryAdvance方法.相比之下,Stream.Builder有一个存储空间,可以在获取Stream之前填充所有流元素.
因此,Spliterator是各种惰性求值的首选,也是您想要遍历的现有存储的首选,以避免复制数据.
当元素的创建是非均匀的时,构建器是第一选择,因此您无法按需创建元素.想想你否则会使用Stream.of(…)的情况,但事实证明它是不灵活的.
例如.你有Stream.of(a,b,c,d,e),但现在结果证明,c和d是可选的.所以解决方案是
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,其中需要消费者来查询现有的分裂器并且之后将值推回到流,或this answer,其中应该以相反的顺序流传输没有随机访问的结构(类层次结构).