巧用Java Stream Gather利器,让你的效率翻个倍
《巧用Java Stream Gather利器,让你的效率翻个倍》共 0.2 万字,通篇围绕 架构、需求、场景 展开,归在「后端与系统架构」这一层。
适合给 AI 系统搭底座、要管得住的人
目录骨架(8 节)
- 一、背景
- 二、什么 是 Stream ?
- 三、各种库有什么不一样
- 四、为什么需要 Stream Gather API?
- 五、分析和对比
- 六、总结
- **问题空间**
- **Stream Collector & Gather**
示例代码
📎 附件:gather-demo.zip(zip, 12KB)
原文链接:https://www.yuque.com/attachments/yuque/0/2024/zip/2424104/1713851578975-6c373772-854a-491e-b989-a90c7c61e384.zip
分享内容
一、Stream 发展背景
二、什么 是 Stream ?
三、各种库有什么不一样
四、为什么需要 Stream Gather API (Java 22)?
五、Stream和Gather对比
六、总结
一、背景
Java Stream 自从 Java 1.8 引入以来,迅速成为了各位开发者手中信手拈来的工具,大家日常在工作中谈论起来也是如数家珍。但由于 Java Stream 的操作符不足够的丰富,经常会遇到捉襟见肘的情况。对于此,大家可能会继而采用操作符更加丰富的库来作为替代。作为 Java 标准库的一部分,Oracle 的 Java 架构师们也一直以来都在探索如何更好的适应日益增长的用户需求和语言的可维护性,随着Java 22 Stream Gather API 的到来,这个情况得到了极大的改善,下面让我结合自身经验,和大家分享 Java Stream Gather API。
二、什么 是 Stream ?
在编程语言生态中,Stream 是一个抽象的概念,代表了一组连续地对数据的处理的操作及流经其的数据,类似汽车生产流水线一样,下面用 “流”来指代。通常来说,”流 “可以分为“有限流” 和“无限流”。如 长江(滚滚长江东逝水) 可以看做一个”无限流 “,沿途的各种水电站可以看做 “流” 中的中间处理节点。通常来说,拆分细致的库可能会将流拆分为 “Source(源)”、“Flow(流处理)”、”Sink(终点)“三个部分,不过在 API 层不一定体现。如下所示:

这些 “Source”、“Flow” 和 “Sink” 的组合,最终形成了一个复杂的处理流图。也就是我们的代码业务逻辑。通常来说,在 Java 中,我们使用的标准库中的 Stream 则可以看做是一个最简单的单向流,如下图所示:

现在我们应该对什么 是 “流” 有了一个清晰的认识了。通常我们如果不需要自己开发 Java Stream 的操作符,因此几乎接触不到 AbstractPipeline 和 Sink 这两个类,当然截止 Java 22, Java Stream 也没有足够的扩展点。
三、各种库有什么不一样
在目前日常工作中,作为 Java 开发者,我们可能会用到多种面向 “流” 的工具包,简单对比如下:

从上可以看到,虽然 Java 标准库的 Stream API 开箱即用,但是在很多特定场景下,我们也不得不选用其他的库;为了改善这一点,Viktor Klang 提出了 Stream Gather API,作为除 Stream Collector 之外的另一个扩展点,来弥补 Java Stream 的短板。
题外话:Viktor Klang 之前是 Akka 的开发团队的一员。
四、为什么需要 Stream Gather API?
问题空间
Java Stream API 目前主要缺乏丰富的 操作符,而如果像其他的库一样添加很多的操作符到 Stream API,又会有较大的维护负担,如果希望只添加有限的操作符,却可以解决绝大部分的问题。则新的操作符需要支持下面的特性:
- 支持多种类型的数据转换:1 :1, 如 map 操作符1 :N, 如 filterN :1, 如 foldN:M, 如 windowFixed
- 支持 “有限流” 和 “无限流”
- 支持 “有状态” 和 “无状态” 操作
- 支持 “提前终止” 和 “全量消费”
- 提前终止(Premature termination):这是指在Stream的处理过程中,由于某些条件,处理被提前中断。例如,在使用limit()方法时,Stream会在达到指定的元素数量后提前终止。
- 全量消费(Full consumption):这是指Stream的元素被完全处理,没有任何元素被提前忽略或跳过。例如,在使用forEach()方法时,Stream中的所有元素都会被消费。
- 支持 “单线程顺序处理” 和 “多线程并行处理”
- 支持感知 “结束”,如实现一个 fold 操作符
Stream Collector & Gather
Java Stream 目前仅提供的了一个扩展点:Collector <T, A, R>, 其包含下面几个部分:
T:stream中的元素类型;
A:累加器的类型,可以想象成一个容器。比如T要累加,转化为List,A就是List类型。
R:最终返回值类型

