如何理解ja8中stream的延迟作的意思?
作者:卡卷网发布时间:2025-01-10 19:21浏览数量:81次评论数量:0次
你贴出来的解释已经很清晰了:
forEach()
、collect()
、reduce()
等,Stream管道(pipeline)才会被<>启动>这里不直接解释什么是延迟作(LazyEvaluation),咱们边写边聊。
<>最终的目的:>写出一个大致符合上面<>两点要求>的SimpleStream(仿Ja8StreamAPI)
手写Stream版本1
很简单,应该都能看懂。然后给上面的Stream写一个:
在终端作forEach
执行前,调用filter时已经开始处理元素了,不符合文章最开始定义的第一条:终端作调用时才启动。
手写Stream版本2
版本2版本1更好理解,而且效果也更好。同样的案例,得到的结果是:
版本2符合第一点定义(其实也符合第二点定义)。
手写Stream版本3
如果再来一个map(),难道要这样?
再来一个peek()呢?再定一个变量保存peek作?很显然,<>为每一种作定义一个变量来存储的做法是不可行的。>
代码迭代到这,从面向对象的角度,一般会倾向于抽象。同为中间作,filter看起来和map有很大的不同,如果把peek也算进来,可的算是一锅乱炖:
返回值完全不同,甚至有些作没有返回值,似乎不好做函数抽象。但是换个角度,这些中间作就像一节节下水管道,水至上而下流过,只有两种可能:
所以,这里打算抽象出一个Stage。
为了简单起见,就不整泛型了,看着烦。
FilterStage和MapStage长啥样呢?
很简单对吧,Stage也没什么大不了的,<>就是把predicate和mapper包一下>,不管内地的、的、的,纵然有这样或那样的不同,都是中国人对吧。用一个更大的抽象概念,去求同存异即可。
既然都是Stage,自然就可以用List<Stage>去<>一存储>所有中间作。
重点看forEach:遍历每一个元素,为每个元素先执行中间作、再执行终端作,如果没有终端作,中间作不会启动(只是被存起来而已)。
至此,开头定义的第一、第二点都符合了。再来一把:
李健被filter了,所以没有后续作。元素也确实是逐个执行,并且仅遍历一次。
手写Stream版本4
为了稍微接近Ja8的StreamAPI,这里再迭代:优化forEach中的process。
process的逻辑是,对当前遍历到的元素,逐个执行所有中间作,内部用的是for循环。现在我要把它改成一种类似<>链式结构,>你也可以叫它责任链,anyway。
怎么引入链式结构呢?这取决于你期望借助链式结构达到什么效果。
如,我期望最终的写法是这样的:
先别管Sink是什么,你可以把它看作另一种Stage,也是对中间作的封装。总之,通过wrapStages(),我们得到了一种链式结构,这条链上有我们通过filter()、map()等方法压入的中间作,<>只要调用sink.accept(element)
,element就会沿着链条执行下去,就像往下水道倒了一碗水。>
开始实施。
目前:stage负责<>封装中间作>
目标
发现了吗,原本stage的职责转移给了sink,它有了新的职责:组装链式结构。
链式结构怎么来的
filter()、map()这些方法只负责存储predicate等作、不涉及组装,等到forEach触发后才会调用wrapStages()组装链式结构。
以filterStage为例:
也就是说,wrap干了两件事:
链式作如何执行
调用forEach开启管道作:
accept是管道作的入口,从filter开始:
代码已上传到git仓库:com/ro/advanced/fluent/stream2
ro1988/design-pattern对设计模式、Ja进阶感兴趣,可以参考以下路线。
ro1988:Ja程序员练级路线免责声明:本文由卡卷网编辑并发布,但不代表本站的观点和立场,只提供分享给大家。
- 上一篇:个人做什么内容才有价值呢?
- 下一篇:计算机专业CPU应该用AMD还是In?
你 发表评论:
欢迎