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中的元素,会经历所有(如果可能)的操作之后,再到下一个元素的执行;
基于这个特性,可以将具有过滤功能的操作,放在前面执行,可以显著减少流的执行次数
filterskipdistinct -
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中的方法