什么是Stream?

Java 8 之前,通常通过 for 循环或者 Iterator 迭代来重新排序合并数据,又或者通过重新定义 Collections.sorts 的 Comparator 方法来实现,这两种方式对于大数据量的系统来说,效率并不是很理想。
Java 8 中添加了一个新的接口类 Stream,集合中的Stream 相当于高级版的 Iterator,可以通过 Lambda 表达式对集合进行便利、高效的聚合操作(Aggregate Operation),或者大批量数据操作(Bulk Data Operation)。
Stream 的聚合操作与数据库SQL 的聚合操作 sorted 、 filter、map 等类似。在应用层就可以高效地实现类似数据库 SQL 的聚合操作,在数据操作方面,Stream 不仅可以通过串行的方式实现数据操作,还可以通过并行的方式处理大批量数据,提高数据处理效率。

案例

需求:过滤分组一所中学里身高在 160cm 以上的男女同学

  • 传统的迭代方式

    1. Map<String, List<Student>> stuMap = new HashMap<String, List<Student>>();
    2. for(Student stu : studentsList) {
    3. if(stu.getHeight() > 160) {
    4. if(stuMap.get(stu.getSex()) == null) {
    5. List<Student> list = new ArrayList<>();
    6. list.add(stu);
    7. stuMap.put(stu.getSex(), list);
    8. } else {
    9. stuMap.get(stu.getSex()).add(stu);
    10. }
    11. }
    12. }
  • Stream API 实现

  1. 串行实现

    1. Map<String, List<Student>> stuMap = stuList.stream().filter((Student s) -> s.getHeight() > 160).collect(Collectors.groupingBy(Student :: getSex));
  2. 并行实现

    1. Map<String, List<Student>> stuMap = stuList.parallelStream().filter((Student s) -> s.getHeight() > 160).collect(Collectors.groupingBy(Student :: getSex));

    Stream 如何优化遍历?

    1.Stream操作分类

    官方将Stream 中的操作分为两大类:中间操作(Intermediate operations)和终结操作(Terminal operations)。

  • 中间操作只对操作进行记录,即只会返回一个流,不会进行计算操作
  • 终结操作是实现了计算操作

中间操作又分为无状态(Stateless)和有状态(Stateful)操作

  • 无状态 —— 元素的处理不受之前元素的影响
  • 有状态 —— 操作只有拿到所有元素之后才能继续下去

终结操作又可分为短路(Short-circuiting)和非短路(Unshort-circuiting)

  • 短路 —— 遇到某些符合条件的元素就可得到最终结果
  • 非短路 —— 必须处理完所有元素才能得到最终结果

06 Stream 如何提高遍历集合效率 - 图1
通常还会将中间操作称为懒操作,也正是由于这种懒操作结合终结操作、数据源构成的处理管道(Pipeline),实现了Stream 的高效

2. Stream 源码实现