Java8——Stream API详解

364 阅读2分钟

1、什么是Stream? Java 8 中的 Stream 是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便利、高效的聚合操作(aggregate operation),或者大批量数据操作 (bulk data operation)。Stream API 借助于同样新出现的 Lambda 表达式,极大的提高编程效率和程序可读性。

#代码示例
Stream.of("one", "two", "three", "four")
                .filter(e -> e.length() > 3)
                .peek(e -> System.out.println("Filtered value: " + e))
                .map(String::toUpperCase)
                .peek(e -> System.out.println("Mapped value: " + e))
                .forEach(System.out::println);

2、Stream操作分类及特点

中间操作

  • 无状态操作,如filter map 等,来一个数据就可以处理一个数据;
  • 有状态操作,如distinct sorted 等,需要知晓全部的数据才可运行,执行有状态操作时慎用并行流parallel;

终止操作

  • 短路操作,满足给定的条件就会停止,不会遍历所有数据,findFirst findAny等
  • 非短路操作,会遍历当前所有的数据 forEach,reduce ,collect

Stream的特点

  • 中间操作并不会立即执行,只是将当前操作加入到stage链中,只有终止操作才会触发stage链的实际调用

  • 数据是垂直执行的,每个Stream中的元素,会经历所有(如果可能)的操作之后,再到下一个元素的执行;

    基于这个特性,可以将具有过滤功能的操作,放在前面执行,可以显著减少流的执行次数 filter skip distinct

  • Stream经过终止操作后就会关闭,不可重复使用

  • 支持采用多线程的并行流,且使用透明,只需.parallel()即可;

IntStream.rangeClosed(1,100).parallel().forEach(i->{
    System.out.println(LocalDateTime.now() + " : " + i);
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) { }
});

3、常用操作

4、调试

  • 可以在任意操作后边加peek(Consumer) 用做调试,不会对数据产生影响,但是生产环境不建议使用
Stream.of("one", "two", "three", "four")
                .filter(e -> e.length() > 3)
                .peek(e -> System.out.println("Filtered value: " + e))
                .map(String::toUpperCase)
                .peek(e -> System.out.println("Mapped value: " + e))
                .forEach(System.out::println);
  • 使用idea,debug时在Stream操作处打断点,点击Trace Current Stream Chain按钮.可以更加直观的看到Stream每一步的操作结果。

5、其他

  • Stream操作最好能够每个操作放一行,这样看起来比较直观,并且有一些map操作的话idea会在末尾显示每次操作完成后的元素类型;
  • 集合操作超过两个步骤时再使用Stream,否则使用for loop更加简单;
  • 复杂计算的情况下再选择使用并行流的方式,日常开发场景使用顺序流就足够了;
  • Collectors中的方法