Joh*_*ler 2 java java-8 java-stream
我正在学习java 8流,有些问题对我而言.
假设这段代码:
new Random().ints().forEach(System.out::println);
Run Code Online (Sandbox Code Playgroud)
它在某种程度上内部称IntPipeline
,我认为有责任无限期地生成这些内容.通过查看java源代码很难理解Streams实现.
您能否给出一个简短的解释,或者给出一些关于如何生成流以及如何连接管道操作的好/易理解的材料.整数上面的代码示例是随机生成的,如何建立这种连接?
Stream实现分为Spliterator
(输入特定代码)和管道(与输入无关的代码).在Spliterator
类似Iterator
.主要区别如下:
它可以将自己分成两部分(trySplit
方法).对于有序的分裂器,部件是前缀和后缀(例如,对于阵列,它可以是前半部分和后半部分).对于无序源(如随机数),两个部分都可以生成一些元素.由此产生的部分能够进一步分裂(除非它们变得太小).此功能对于并行流处理至关重要.
它可以报告其大小或精确或估计.确切的大小可以用于为某些流操作预分配内存,toArray()
或者只是将其返回给调用者(如count()
Java-9).估计的大小用于并行流处理以决定何时停止分割.
它可以报告一些特征,如ORDERED,SORTED,DISTINCT等.
它实现了内部迭代:而不是两个方法hasNext
,next
你有一个方法tryAdvance
执行提供的Consumer
一次,除非没有更多的元素.
也有原始专业化Spliterator
接口(Spliterator.OfInt
等),它可以帮助您处理类似的原始值int
,long
或double
有效.
因此,要创建自己的Stream数据源,必须实现Spliterator
,然后调用StreamSupport.stream(mySpliterator, isParallel)
以创建Stream
和StreamSupport.int/long/doubleStream
原始特化.所以实际上Random.ints
调用StreamSupport.intStream
提供自己的分裂器.您不必Stream
自己实施所有操作.通常Stream
,对于不同的源,在JDK中每个流类型仅实现一次接口.有基本的抽象类AbstractPipeline
和四个实现(ReferencePipeline
for Stream
,IntPipeline
for IntStream
,LongPipeline
for LongStream
和DoublePipeline
for DoubleStream
).但是,你有更多的来源(Collection.stream()
,Arrays.stream()
,IntStream.range
,String.chars()
,BufferedReader.lines()
,Files.lines()
,Random.ints()
等等,甚至更多地出现在Java-9中.所有这些来源都是使用自定义分裂器实现的.实现它Spliterator
比实现整个流管道(特别是考虑到并行处理)要简单得多,因此这种分离是有意义的.
如果要创建自己的流源,可以开始扩展AbstractSpliterator
.在这种情况下,您只需要实现tryAdvance
并调用超类构造函数,以提供估计的大小和一些特征.在AbstractSpliterator
通过读取源的一部分进入阵列(调用你的实现提供了默认的分裂行为tryAdvance
方式)和创建这个前缀基于阵列的spliterator.当然,这种策略性能不是很高,而且往往只提供有限的并行性,但作为一个起点,它是可以的.稍后您可以trySplit
自己实施提供更好的拆分策略.
归档时间: |
|
查看次数: |
1013 次 |
最近记录: |