关于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学习之内部迭代与外部迭代本质剖析及流本源分析的更多相关文章

  1. java8学习之收集器枚举特性深度解析与并行流原理

    首先先来找出上一次[http://www.cnblogs.com/webor2006/p/8353314.html]在最后举的那个并行流报错的问题,如下: 在来查找出上面异常的原因之前,当然得要一点点 ...

  2. JAVA8学习——从使用角度深入Stream流(学习过程)

    Stream 流 初识Stream流 简单认识一下Stream:Stream类中的官方介绍: /** * A sequence of elements supporting sequential an ...

  3. 初探Lambda表达式/Java多核编程【0】从外部迭代到内部迭代

    开篇 放假前从学校图书馆中借来一本书,Oracle官方的<精通Lambda表达式:Java多核编程>. 假期已过大半才想起来还没翻上几页,在此先推荐给大家. 此书内容及其简洁干练,如果你对 ...

  4. NumPy 超详细教程(3):ndarray 的内部机理及高级迭代

    系列文章地址 NumPy 最详细教程(1):NumPy 数组 NumPy 超详细教程(2):数据类型 NumPy 超详细教程(3):ndarray 的内部机理及高级迭代 ndarray 对象的内部机理 ...

  5. PythonI/O进阶学习笔记_8.python的可迭代对象和迭代器、迭代设计模式

     content: 1.什么是迭代协议 2. 什么是迭代器(Iterator)和可迭代对象(Iterable) 3. 使用迭代器和可迭代对象 4. 创建迭代器和可迭代对象 5. 迭代器设计模式   一 ...

  6. hive学习笔记之三:内部表和外部表

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  7. 大数据学习day26----hive01----1hive的简介 2 hive的安装(hive的两种连接方式,后台启动,标准输出,错误输出)3. 数据库的基本操作 4. 建表(内部表和外部表的创建以及应用场景,数据导入,学生、分数sql练习)5.分区表 6加载数据的方式

    1. hive的简介(具体见文档) Hive是分析处理结构化数据的工具   本质:将hive sql转化成MapReduce程序或者spark程序 Hive处理的数据一般存储在HDFS上,其分析数据底 ...

  8. java8学习之深入函数式接口与方法引用

    函数式接口: 函数式接口[FunctionalInterface]是整个Lambda表达式的一个根源,换句话来说java8中的Lambda表达式要想彻底掌握,前提是要彻底理解好函数式接口,所以这次继续 ...

  9. JAVA8学习——深入浅出Lambda表达式(学习过程)

    JAVA8学习--深入浅出Lambda表达式(学习过程) lambda表达式: 我们为什么要用lambda表达式 在JAVA中,我们无法将函数作为参数传递给一个方法,也无法声明返回一个函数的方法. 在 ...

随机推荐

  1. python programming GUI综合实战(在GUI上画图)

    import os import platform import sys from PyQt5.QtCore import * from PyQt5.QtGui import * from PyQt5 ...

  2. iOS检测用户截屏, 并获取所截图片

    // // ViewController.m // CheckScreenshotDemo // // Created by 思 彭 on 2017/4/25. // Copyright © 2017 ...

  3. Laravel6.0 使用 Jwt-auth 实现多用户接口认证

    后台管理员认证 (admins 表) 首先创建数据库和表 (admins),在 routes/api.php 中,写上如下路由并创建对应控制器和方法. Route::namespace('Api')- ...

  4. 我想学前端动画-CSS之transition

    Transition属性: 属性 描述 CSS transition 简写属性,用于在一个属性中设置四个过渡属性. 3 transition-property 规定应用过渡的 CSS 属性的名称.默认 ...

  5. ASP.NET Session详解(转)

    ASP.NET Session详解 本文章来自:http://blog.163.com/adam601@126/blog/static/22506317200932824210996/ 当用户在 We ...

  6. java并发学习资料

    1.Java 并发编程知识梳理以及常见处理模式 https://github.com/Fadezed/concurrency 2.Java 高并发多线程编程系列 https://github.com/ ...

  7. java 实现读取某个目录下指定类型的文件

    我这里是读取txt类型的文件,在指定的目录下有不同类型的文件 实现代码,读取txt类型的文件并打印出该文件的绝对路径 package com.SBgong.test; import java.io.F ...

  8. Spring(十一)-- Spring代理生成器

    Spring代理生成器 1.创建需要的dao接口 2.创建需要的daoImpl实现类 3.创建前置增强类 4.创建spring.xml文件 <!-- 这个案例 需要解决的问题: 一个代理工厂 配 ...

  9. 设计模式:模板方法(Template method)

    首先我们先来看两个例子:冲咖啡和泡茶.冲咖啡和泡茶的基本流程如下: 所以用代码来创建如下: 咖啡:Caffee.java public class Coffee { void prepareRecip ...

  10. table表格的无缝循环

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...