java8学习之内部迭代与外部迭代本质剖析及流本源分析
关于Stream在Java8中是占非常主要的地位的,所以这次对它进行进一步探讨【这次基本上都是偏理论的东东,但是理解它很重要~】,其实流跟咱们数据库学习当中的sql语句的特点是非常非常之像的,为什么这么说,下面以这个sql语句举例说明:
“select name from student where age > 20 and address = 'beijing' order by age desc;”
该简单的sql所要表达的意思是:从student这张表中查询出年龄>20并且地址=北京的记录,并且对年龄进行降序排序,排序之后将其名字查找出来。对于sql其实是一个描述性的语言,只描述其行为,而具体如何让db完成这个行为是没有暴露出来的,对于该sql所做的工作如果换成咱们的stream来实现那会是个什么样子呢,下面写一下伪代码:
首先从源数据中获得stream:
students.stream();
接着进行条件过滤:age > 20 and address = 'beijing',如下:
students.stream().filter(student -> student.getAge() > 20).filter(student -> student.getAddress().equals("beijing"));
然后对年纪进行排序,这里写伪代码:
students.stream().filter(student -> student.getAge() > 20).filter(student -> student.getAddress().equals("beijing")).sorted(...);
最后将其名字打印出来,如下:
students.stream().filter(student -> student.getAge() > 20).filter(student -> student.getAddress().equals("beijing")).sorted(...).forEach(student -> System.out.println(student.getName()));
是不是从表现形式上跟sql语句差不多,Stream也是属于一种描述性的语句, 整个语句并没有告诉底层Stream要如何去做,等于只要发一些指令给底层就可以了,具体底层怎么做完全不用关心。
其实对于这种Stream()的这种方式是一种内部迭待,而如果换成传统的方式既为外部迭待方式,如下:
List<Student> list = new ArrayList<>(); //首先对数据进行条件过滤
for(int i=0; i < students.size();i++){
Student student = students.get(i);
if(student.getAge() > 20 && student.getAddress().equals("beijing")){
list.add(student);
}
} //接着对其按年龄排序
Collections.sort(list. Comparator()...); //将名字打印出来
for(Student student : list){
System.out.println(student.getName());
}
是不是发现跟使用Stream的方式完全没法相比,相差太多了,而且本质上也有区别,之所以上面传统的方式为外部迭待,很显然用到了一个中间的临时变量,另外将业务条件跟具体遍历代码都混在一起了,语义上理解也没这么容易,假如说对于一个不懂代码的人来看这两种实现方式,肯定是看具有描述性语句的stream的方式更加容易理解。
接下来用图的方式来阐述一下内部迭待与外部迭待的本质区别:
外部迭待:
针对一个集合:

以咱们这个例子为例,会使用for循环对其进行迭待,所以会单独在集合之外写入咱们自己的处理逻辑,如下:

其中集合与咱们自己编写的处理逻辑之间是有清晰的划分的:


内部迭待:
那对于stream的内部迭待方式表现又如何呢?
首先操作的对象就不是集合啦,而是集合的流,如下:

而接下来内的体现就来了,咱们自己写的代码和流会融合在一起了,而非自己写的这块代码相对于流是独立的:

合并到一起有什么好处呢?这样流就可以拿到咱们自己所提供的代码进行相应的优化,当遇到咱们调用的终止操作则将咱们提供的所有中间操作与流之前所提供好的基础功能进行统一的处理。
其实内部迭待有点像是做填充题一样,对于一篇写好的英文文章,空缺了几个填充选项【将某个单词或某个语句被扣出来了】,而咱们写的代码其实就是填补这些空缺的地方,而不是完全由自己发挥想象来写这篇英文文章;而传统的外部迭代方式则是给一个命题里面所有的内容都得由自己来编写。
另外内部迭待与外部迭待还有另外一个最大的区别,那就是内部迭待支持并行处理,而所有的并行处理其stream都已经代替咱们来处理了,也就是从调用者的角度来想就不用关心处理并行的问题,而传统的外部迭待一般都是串行的,如果也想要并行处理那这个并行的东东完全得自己来处理。
对于集合和流最后再来用一句话来概括:集合关注的是数据与数据存储本身;流关注的则是对数据的计算。而流与迭待器类似的一点是:流是无法重复使用或消费的。
另外对于流再来说明一下:对于流来说,中间操作都会返回一个Stream对象,而终止操作则不会返回Stream类型,它可能不返回值,也可能返回其它类型的单个值。所以说区分中间操作与终止操作的条件就是看返回的类型,如果是Stream对象一定是中间操作。
java8学习之内部迭代与外部迭代本质剖析及流本源分析的更多相关文章
- java8学习之收集器枚举特性深度解析与并行流原理
首先先来找出上一次[http://www.cnblogs.com/webor2006/p/8353314.html]在最后举的那个并行流报错的问题,如下: 在来查找出上面异常的原因之前,当然得要一点点 ...
- JAVA8学习——从使用角度深入Stream流(学习过程)
Stream 流 初识Stream流 简单认识一下Stream:Stream类中的官方介绍: /** * A sequence of elements supporting sequential an ...
- 初探Lambda表达式/Java多核编程【0】从外部迭代到内部迭代
开篇 放假前从学校图书馆中借来一本书,Oracle官方的<精通Lambda表达式:Java多核编程>. 假期已过大半才想起来还没翻上几页,在此先推荐给大家. 此书内容及其简洁干练,如果你对 ...
- NumPy 超详细教程(3):ndarray 的内部机理及高级迭代
系列文章地址 NumPy 最详细教程(1):NumPy 数组 NumPy 超详细教程(2):数据类型 NumPy 超详细教程(3):ndarray 的内部机理及高级迭代 ndarray 对象的内部机理 ...
- PythonI/O进阶学习笔记_8.python的可迭代对象和迭代器、迭代设计模式
content: 1.什么是迭代协议 2. 什么是迭代器(Iterator)和可迭代对象(Iterable) 3. 使用迭代器和可迭代对象 4. 创建迭代器和可迭代对象 5. 迭代器设计模式 一 ...
- hive学习笔记之三:内部表和外部表
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- 大数据学习day26----hive01----1hive的简介 2 hive的安装(hive的两种连接方式,后台启动,标准输出,错误输出)3. 数据库的基本操作 4. 建表(内部表和外部表的创建以及应用场景,数据导入,学生、分数sql练习)5.分区表 6加载数据的方式
1. hive的简介(具体见文档) Hive是分析处理结构化数据的工具 本质:将hive sql转化成MapReduce程序或者spark程序 Hive处理的数据一般存储在HDFS上,其分析数据底 ...
- java8学习之深入函数式接口与方法引用
函数式接口: 函数式接口[FunctionalInterface]是整个Lambda表达式的一个根源,换句话来说java8中的Lambda表达式要想彻底掌握,前提是要彻底理解好函数式接口,所以这次继续 ...
- JAVA8学习——深入浅出Lambda表达式(学习过程)
JAVA8学习--深入浅出Lambda表达式(学习过程) lambda表达式: 我们为什么要用lambda表达式 在JAVA中,我们无法将函数作为参数传递给一个方法,也无法声明返回一个函数的方法. 在 ...
随机推荐
- web容器启动加载WebApplicationContext和初始化DispatcherServlet
原文地址:http://blog.csdn.net/zghwaicsdn/article/details/51186915 ContextLoaderListener监听器,加载ROOT WebApp ...
- Xing: The Land Beyond — 从课堂到 Steam* 的卓越之旅
Xing:The Land Beyond 的诞生最初源于大学的一个关卡设计课程,之后才登录 Kickstarter* 平台,采用虚拟现实技术,并由 Sony* 带到电子娱乐展览会.这个设计任务本来计划 ...
- Unity中的动画系统和Timeline(3) 模型和动画导入
动画导入 美工做好的模型,直接将文件夹拖进来就导入好了.导入模型后,检查模型的材质贴图等是否丢失,若丢失,根据名字补上.如果美工取名规范,一一对应的话,就很简单.如果不是,那就呵呵哒. 有的美工做的比 ...
- 关于torchvision.datasets.CIFAR10
在Pytorch0.4版本的DARTS代码里,有一行代码是 trn_data = datasets.CIFAR10(root=data_path, train=True, download=False ...
- Leetcode之广度优先搜索(BFS)专题-279. 完全平方数(Perfect Squares)
Leetcode之广度优先搜索(BFS)专题-279. 完全平方数(Perfect Squares) BFS入门详解:Leetcode之广度优先搜索(BFS)专题-429. N叉树的层序遍历(N-ar ...
- C学习笔记-makefile
除非最简单的项目,任何一个商业项目都会包含多个源代码,而且在编译的时候会有很长很复杂的指令,为了编译的简单可行,makefile由此而生,在编译时候直接输入make便会按照makefile里面的规则编 ...
- 【Spring AOP】Spring AOP的使用方式【Q】
Spring AOP的三种使用方式 经典AOP使用方式 改进XML配置方式 基于注解的方式 第1种方式可以作为理解spring配置AOP的基础,是最原始的配置方式,也体现了spring处理的过程. 使 ...
- windows vue环境搭建
windows环境搭建Vue开发环境 一.安装node.js(https://nodejs.org/en/) 下载完毕后,可以安装node,建议不要安装在系统盘(如C:). 二.设置nodejs pr ...
- linux 在线安装jdk
1. yum -y list java* 2.yum -y install java-1.8.0-openjdk*
- 关于前端JS判断字符串是否包含另外一个字符串的方法总结
RegExp 对象方法 test() var str = "abcd"; var reg = RegExp(/d/); console.log(reg.test(str)); // ...