最近在项目上用的挺多 Stream API 的,只是觉得用的很爽!可是不太了解它的原理。今天偶然在收集 gateway 的技术方案的时候看到了 3y 的文章,不错学习下!
3y 理解的Stream流编程就是:某些场景会经常用到操作(求和/去重/过滤….等等),已经封装好API给你了,你自己别写了,调我给你提供的API就好了。
1.支持并发
回到我们最原始的代码:
public static void main(String[] args) {
int[] nums = { 1, 2, 3 };
int sum = 0;
for (int i : nums) {
sum += i;
}
System.out.println("结果为:" + sum);
}
如果我们想要for
循环的内部支持并发的话,显然不太好去写。但使用Stream流的方式,调用一个方法就可以支持并发(parallel):
public static void main(String[] args) {
int[] nums = { 1, 2, 3 };
int sum2 = IntStream.of(nums).parallel().sum();
System.out.println("结果为:" + sum2);
}
原理
使用Stream流分为三步:
- 创建Stream流
- 通过Stream流对象执行中间操作
- 执行最终操作,得到结果
创建流
创建流我们最常用的就是从集合中创建出流
/**
* 返回的都是流对象
* @param args
*/
public static void main(String[] args) {
List<String> list = new ArrayList<>();
// 从集合创建
Stream<String> stream = list.stream();
Stream<String> stream1 = list.parallelStream();
// 从数组创建
IntStream stream2 = Arrays.stream(new int[]{2, 3, 5});
// 创建数字流
IntStream intStream = IntStream.of(1, 2, 3);
// 使用random创建
IntStream limit = new Random().ints().limit(10);
}
执行中间操作
怎么理解中间操作?意思是这样的:在上面我们已经能创建出Stream了,我们是对Stream进行操作,对Stream操作返回完返回的还是Stream,那么我们称这个操作为中间操作。
因为中间操作(filter,map,foreach)返回的都是流对象,所以我们可以链式调用。
注意:Stream上的操作并不会立即执行,只有等到用户真正需要结果的时候才会执行(惰性求值)。
执行最终操作
最终操作返回的不再是Stream对象,调用了最终操作的方法,Stream才会执行。
总结
使用Stream的原因我认为有两个:
- JDK库提供现有的API,代码写起来简洁优化
- 方便并发。大家可以记住一个结论:在多核情况下,可以使用并行Stream API来发挥多核优势。在单核的情况下,我们自己写的
for
性能不比Stream API 差多少