java8新特性-Stream
—–通过学习尚硅谷视频所得—–
前言
咱们在sql中,可以对集合进行增删改插入和统计,但是在java程序中,对于一些集合, 都是通过循环的方式来处理里面的数据的.所以,对于大数量的集合,能不能充分利用多核的优势,并行去处理.
这里就来介绍一种这样的处理数据的风格—Stream
这种特性的引入,让我们更加便利一些函数式编程方法的使用.可以充分利用系统并行能力,不需要自己手工去做很多底层的工作.
定义
集合讲的是数据,流讲的是计算
Jenkins有这么一个概念pipeline. linux脚本命令中也会有一些接触.正常一个模块只专注于做一件事情,他们之间通过流水线方式连接起来.
从函数式编程的理论角度来说, stream 表示的是一个叫monad的结构. 具体monad 参考这篇博客:http://www.ruanyifeng.com/blog/2015/07/monad.html
使用
创建流
//1.可以通过Collection 系列集合提供的stream()方法或parallelStream() 顺序流或并行流
List<String> list=new ArrayList<>();
Stream<String> stream1=list.stream();
//2.通过Arrays 中的静态方法 stream()获取数组流
Employee[] emps=new Employee[10];
Stream<Employee> stream2=Arrays.stream(emps);
//3.通过stream类中的静态方法of(),通过显示值创建一个流,可以接受任意数量的参数
Stream<String> stream3=Stream.of("aa","bb","cc");
//4.函数创建流:创建无线流
Stream<Integer> stream4= Stream.iterate(0,(x) -> x+2);
stream4.limit(10).forEach(System.out::print);
//生成
Stream.generate(()-> Math.random())
.limit(5)
.forEach(System.out::println);
中间操作
惰性操作
流是一种惰性操作,除非流水线上触发终止操作,否则中间操作不会执行任何的处理!而在终止操作时一次性全部处理
List<Employee> employees = Arrays.asList(
new Employee("张三", 18, 9999.99),
new Employee("李四", 58, 5555.55),
new Employee("王五", 36, 3333.33),
new Employee("田七", 12, 8888.88)
);
来个小例子: 取出员工年龄大于35岁的
Stream<Employee> stream = employees.stream()
.filter((e) -> {
System.out.println("Stream API的中间操作");
return e.getAge() > 35;
});
这里没有写终止操作,那么打印没有任何内容
如果现在加上了终止操作
Stream<Employee> stream = employees.stream()
.filter((e) -> {
System.out.println("Stream API的中间操作");
return e.getAge() > 35;
});
//终止操作,即惰性求值
stream.forEach(System.out::println);
我们来看效果:
而在终止操作时将中间操作一次性全部处理
stream执行顺序:
是按照流水线的方式执行的,不需要额外利用集合的数据结构来保存中间结果的.
举个例子:
筛选和切片
- filter-接收Lambda,从流中排除某些元素
- limit-截断流,使其元素不超过该给定数量
- skip(n) -跳过元素,返回一个扔掉了前n个元素的流.若流中元素不足n个,则返回一个空流.与limit(n)互补
- distinct-筛选,通过流生成元素的hashCode()和equals()去除重复元素
映射
- map-接收Lambda,将元素转换成其他形式或提取信息.接收一个函数作为参数,该参数会被应用到每一个元素上,并将其映射成一个新的元素.
- flatMap-接收一个函数作为参数,将流中的每一个值都换成另一个流.然后把所有流连接成一个流
排序
- sorted()-自然排序(Comparable)
- sorted(Comparator com)-定制排序(Comparator)
终止操作
在讲中间操作的时候,我们看上面的代码:filter运算仅仅过滤了stream里的元素,返回的依然是一个Stream类型.如果我们有一些类型转换的话,实际上也只是将一种类型参数的stream转换成另一种stream. 二终止操作, 它是将一个stream转换成了一个list或者toset设置void等等. 这些方法才称之为终止运算方法.
查找和匹配
- allMatch–检查是否匹配所有元素
- anyMatch–检查是否至少匹配一个元素
- noneMatch–检查是否没有匹配所有元素
- findFirst–返回第一个元素
- findAny–返回当前流中的任意元素
- count–返回流中元素的总个数
- max–返回流中最大值
- min–返回流中最小值
- foreach–内部迭代
规约
- reduce 可以将流中元素反复结合起来,得到一个值
收集
- collect-将流转换为其他形式,接收一个Collector接口的实现,用于给Stream中元素做汇总的方法
并发parallelStream
引入的Fork/Join并行计算框架,能通过并行方式来拆分任务.不需要自己编写一行多线程的代码,就可以写出高性能的并发程序
总结
stream遵循的原则是: 告诉我做什么,别管我怎么做的.一个stream pipeline中,首先得有一个数据源,可能是数组或集合. 而在流操作过程中不会修改源中的数据.有多个中间操作,每个中间操作会将接受到的流转换成另一个流. 最后有一个终止操作,会生成一个最终结果.
不像传统数据结构, 事先分配内存空间, 啥时候用,啥时候再计算.默认是串行执行.也有简单支持并行计算的.
推荐阅读