Java 性能调优实战
刘超
前金山软件技术经理
59174 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 49 讲
开篇词 (1讲)
模块一 · 概述 (2讲)
结束语 (1讲)
Java 性能调优实战
15
15
1.0x
00:00/00:00
登录|注册

06 | Stream如何提高遍历集合效率?

非短路操作
短路操作
有状态操作
无状态操作
数据处理过程
Sink链表的生成
Stage的生成
Sink接口
ReferencePipeline结构类
BaseStream和Stream接口
终结操作
中间操作
Stream的使用场景
并行处理操作
串行处理操作
Stream的设计实现
合理使用Stream的建议
多核CPU和单核CPU环境下的性能
性能测试对比
Stream操作叠加
Stream源码实现
Stream操作分类
Stream的聚合操作
Java8中的Stream接口
大数据量系统中的分表分库
思考题
总结
合理使用Stream
Stream如何优化遍历?
什么是Stream?
Java Stream API

该思维导图由 AI 生成,仅供参考

你好,我是刘超。
上一讲中,我在讲 List 集合类,那我想你一定也知道集合的顶端接口 Collection。在 Java8 中,Collection 新增了两个流方法,分别是 Stream() 和 parallelStream()。
通过英文名不难猜测,这两个方法肯定和 Stream 有关,那进一步猜测,是不是和我们熟悉的 InputStream 和 OutputStream 也有关系呢?集合类中新增的两个 Stream 方法到底有什么作用?今天,我们就来深入了解下 Stream。

什么是 Stream?

现在很多大数据量系统中都存在分表分库的情况。
例如,电商系统中的订单表,常常使用用户 ID 的 Hash 值来实现分表分库,这样是为了减少单个表的数据量,优化用户查询订单的速度。
但在后台管理员审核订单时,他们需要将各个数据源的数据查询到应用层之后进行合并操作。
例如,当我们需要查询出过滤条件下的所有订单,并按照订单的某个条件进行排序,单个数据源查询出来的数据是可以按照某个条件进行排序的,但多个数据源查询出来已经排序好的数据,并不代表合并后是正确的排序,所以我们需要在应用层对合并数据集合重新进行排序。
在 Java8 之前,我们通常是通过 for 循环或者 Iterator 迭代来重新排序合并数据,又或者通过重新定义 Collections.sorts 的 Comparator 方法来实现,这两种方式对于大数据量系统来说,效率并不是很理想。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

Java8中的Stream API为集合的遍历和操作提供了高效的解决方案。通过Stream的中间操作和终结操作,可以实现对大数据集合的高效处理。Stream的实现原理是通过BaseStream和Stream接口类、ReferencePipeline结构类以及Sink接口协议来定义整个Stream操作的调用链。通过Stream的串行和并行实现,可以提高数据的处理效率。然而,并行处理并不总是性能更佳,需要根据应用场景进行选择。因此,合理使用Stream API能够提高系统性能,特别是在处理大数据集合时。 总结:Stream的设计实现非常值得学习。它将操作分解为链式结构,简化了遍历操作,为并行计算打下了基础。Stream将遍历元素的操作和对元素的计算分为中间操作和终结操作,实现了链结构中的不同阶段。在串行处理操作中,Stream通过迭代器进行数据处理;在并行处理操作中,Stream结合ForkJoin框架对集合进行切片处理。需要注意Stream的使用场景。 思考题:存在的问题是并行处理时,对共享的容器进行了并发修改,可能导致线程安全问题。建议使用线程安全的容器或进行适当的同步处理。 这篇文章介绍了Java8中Stream API的设计原理和实现方式,以及在并行处理中可能遇到的问题,对于想要了解Stream API的读者来说,是一篇值得阅读的文章。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Java 性能调优实战》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(68)

  • 最新
  • 精选
  • (´田ω田`)
    感觉这一节课已经值回了整个课程的票价,给老师点赞! 思考题:Stream并行执行,无法确认每个元素的处理顺序,最后parallelList中的数字是无序的

    作者回复: 思考题中的问题是在并行操作arraylist时,需要考虑线程安全问题

    2019-06-01
    13
  • 一路看风景
    老师您好,在容器盛行的微服务环境下,以及大数据处理流行的潮流中,我觉得stream的应用空间多少有些尴尬呢,不知是不是我的理解有误。即:单核容器运行的环境下stream没了性能优势,大数据的处理又有大数据平台去完成使命,所以是不是意味着我们可以从stream得到的最大收益变成了流式编程和函数式编程带来的代码易读和易用性了呢?

    作者回复: 是的,但未必所有公司都有构建大数据的能力,而且一些公司有自己的中间件团队,例如文章开始说到的分表分库的查询操作,使用stream的并行操作就有优势了

    2019-06-01
    2
    11
  • 阿厚
    老师,请教2个问题: 1.有什么分表分库中间件推荐么? 2.分表分库以后,查询分页怎么办呢?

    作者回复: 之前用过sharing-jdbc以及mycat,一个明显的区别是sharing-jdbc是嵌入方式,而mycat是基于proxy,所以理论上来说 proxy方式会有性能损耗。现在我们在使用sharing-jdbc,这里不打广告,两个中间件都有自己的优势。 分页查询是基于我这篇文章说的方式,将每个分表的数据结果集查询出来,通过归并排序计算出。 具体的实现方式有区别,本次专栏的后面课程也会具体讲到。

    2019-06-06
    8
  • 辉煌码农
    allMatch为什么是短路呢,短路的如何定义的呢

    作者回复: 终结操作又可以分为短路(Short-circuiting)与非短路(Unshort-circuiting)操作,前者是指遇到某些符合条件的元素就可以得到最终结果,后者是指必须处理完所有元素才能得到最终结果。 allMatch也是属于遇到某些条件的情况下可以终结的操作,即找到一个不合法条件的,短路返回false ,无需等待其他的处理结果,所以也属于短路。

    2020-01-02
    7
  • 圣西罗
    老师,现在网上有些说法做测试用lambda比普通for循环速度慢五倍,因此有人拒绝用。实际情况是什么样呢?如果我自己想测,应该怎么尽可能排除外因干扰,测一下他们的实际效率对比?

    作者回复: 当应用程序以前没有使用lambda表达式时,会动态生成lambda目标对象,这是导致慢的实际原因。我们可以在运行加载后,也就是初次测试之后,紧接着后面加几个for循环,再测试几次,对比下性能。 虽然单独使用lambda表达式在初次运行时要比传统方式慢很多,但结合stream的并行操作,在多核环境下还有有优势的。

    2019-06-01
    2
    6
  • QQ怪
    是不是该把思考题中的arraylist换成线程安全的copyOnwriteList就可以解决线程不安全问题?

    作者回复: 对的,但copyOnwriteList更适合某一时间段统一新增,且新增时避免大量操作容器发生。比较适合在深夜更新黑名单类似的业务。

    2019-06-03
    5
  • Loubobooo
    parallelList集合里呈现的是无序的数字,是这样吗?

    作者回复: 对的,可能会出现少数字、无序以及异常情况

    2019-06-01
    4
  • Mr wind
    为什么聚合操作是线程安全的呢。

    作者回复: Java8 Stream的collect方法是线程安全的。

    2019-12-08
    3
  • Andy
    感觉stream这种中间操作和终结操作 跟spark中转换操作和处理操作 思想很像,懒加载

    作者回复: 是的,好的实现思想会被应用到各个地方

    2019-10-21
    3
  • N
    老师有个问题请教一下,公司业务代码中有大量stream对集合遍历,过滤,聚合的用法,但都是串行的,因为大部分数据量不是很大,请问数据量多大的时候才有必要使用并行提高效率呢?

    作者回复: 上万数量级使用并行可以提高效率。

    2019-07-14
    3
收起评论
显示
设置
留言
68
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部