java stream API初探(二):为了高效
来源:互联网 发布:连环杀人知乎 编辑:程序博客网 时间:2024/05/18 12:33
在尝试使用stream api后,如果不了解stream api背后的优化机制,肯定会产生担心,觉得它中看不中用。本文就是为了消解这类担忧而写。
好的api不仅让你用得方便,还要让你用的放心。stream api已经进行了效率上的优化,能满足多数情况下所需的高效。
比如当你遍历序列,搜寻特定值时,希望一旦得到结果则立即返回,而不是遍历全部值。有时,判断元素满足特定条件的过程十分复杂,更应该尽可能减少判断次数。注重程序效率的你,一定会在普通的循环中进行条件判断加以剪枝,对这些情况进行优化。也许在你看来,具体场景下的优化措施各异,而stream api 通过关注其中的公共点,不露痕迹地完成繁琐的优化任务。
我们先通过一个具体的例子,说明stream api如何进行优化,顺带引入它的一些概念。
下面的例子,是搜寻许多学生中满足特定条件的学生。
class Student{ private int age; boolean fun(){ //极为耗时的操作,例如查询数据库等 //进行一些判断,返回布尔值 } int age(){ return age; }}
List<Student> students = new ArrayList<Student>();//填充students,假设students中包含100万个student对象students.stream() .filter(Student::fun) .map(stu->return stu.age()) .findAny();//注意这里的findAny
在上面的代码中,目的是为了找出能使fun()返回true的Student对象,并返回这个student的age属性。假设Student::fun方法是极为耗时的,并且序列包含海量对象。那么这种时候,我们要避免处理不必要的元素,找到满足条件的学生就执行后续操作。
考察程序执行过程,一种显而易见的处理方式是,程序先对所有对象进行了filter,再取出过滤后的student对象的age属性,最后选择其中任意一个值。
但是这个过程存在极大浪费,更加合理的过程应该是,在遍历的同时,每访问一个student对象,就执行fun方法,如果返回true,则取其age属性值。这样就可能减少fun的执行次数,对元素的访问次数。stream api正是这样做的。
那么它是如何实现这点的呢?通过了解两个概念来回答这个问题。
1.intermediate and terminal operation
中间操作与终止操作。
前面一篇文章已经提到过stream中的pipeline,意指多个操作的组合。一个pipeline中可以有任意个中间操作,但最后的必须是终止操作,且只有一个终止操作。这并非语法上的要求。但假如一个pineline只包含中间操作,那么它没有任何实际效果,即任何操作都没有执行。只有当终止操作存在时,操作才能真正执行。
举例说明:
//符合语法,但无任何意义students.stream().filter(Student::fun());
上面代码中的fun方法,一次都不会执行。你可以在fun中加入输出语句进行验证。这是因为,filter是一个中间操作(intermediate operation)。要想使这句话产生实际效果,末尾需要加一个终止操作,例如findAny,max。
在stream api文档中,会明确指出某个操作属于中间操作或终止操作。如果你把这些操作全部了解一遍,你会发现它们的返回值或是含义是有规律可循的。中间操作只能返回一个Stream对象,含义是对原有stream进行某种映射得到新的stream;终止操作往往返回一个具体对象,含义是从stream中推出某个结果。
2.lazy stream
一个pineline的执行过程,是每当从原stream中取出一个元素,就令它通过所有中间操作,直到终止操作。如果终止操作的执行,需要其它元素参与,如max,min(需要和其余元素比较),则进行等待。如果终止操作的执行不需要其他元素的参与,如findAny,则直接返回结果。
回到对效率问题的解答。在上面示例中,从stream中取出一个元素时,首先经过filter,map,最终到达findAny。因为findAny的执行不需要其它元素的参与,所以就直接得到结果,避免了多余的访问。
以上是stream api对pipeline执行过程的设计。除此之外,我们常用的优化方法是,将串行变为并行。而stream api的底层实现也考虑到了这一点,这是你从表面完全看不到的。
结语:
当这些设计呈现在我面前时,除了解除我对效率的担忧,还让我感到抽象的力量。从低层角度看,每个问题的优化策略都是不同的,但是stream api可以通过提取其中的共同点,解决其中的关键问题,在高层角度解决了大部分情况的优化问题。
- java stream API初探(二):为了高效
- java stream API初探(一):为了简洁
- Java Stream初探(二)
- PHP Stream API初探
- JAVA SE 8 学习笔记(二)Stream API
- Java 8 Stream API
- Java 8 Stream API
- java stream api介绍
- java stream api
- Java 高效并发编程初探
- java twitter stream api & mongoDB
- Java 8 Stream API详解
- Hdfs Java API初探
- JAVA 8 Stream API 对Stream进行分组、分区
- java 初探(二)
- Stream API:创建Stream
- ZooKeeper的Java Api初探
- Java 8新特性:Stream API
- Format 函数,%f,%d,%x,%p
- android读取usb设备数据
- android json处理
- Axure 原型设计工具画业务流程图
- JAVA 入坑教程 | 对象和类
- java stream API初探(二):为了高效
- 1005. 继续(3n+1)猜想 (25)
- 工作组电脑申请域证书
- shell脚本
- 1.C#:数组、ArrayList和List三者的区别
- 魅族手机webview title获取不到
- stanfordSentimentTreebank 的映射关系
- 利用计算器 来转换二,十,十六进制
- python使用问题