java8学习之Stream介绍与操作方式详解
关于默认方法【default method】的思考:
在上一次【http://www.cnblogs.com/webor2006/p/8259057.html】中对接口的默认方法进行了学习,那在Java8中在接口中接出默认方法是为了解决什么问题或者说规避什么问题呢?凡是在JDK引入一个新的概念肯定是专家们经过了一定的权衡才加入的,那加入默认方法的具体原因是啥呢?其实主要是为了解决Java8的向后兼容问题,因为毕境如今Java是一个历史非常优久且用JAVA老版本的系统也非常非常之多了,不可能因为升级到了JAVA8之后由于加入了某种新特性就造成老的系统用不了了,下面拿咱们之前使用过的List接口里面的在Java8中新加入的sort()方法来理解一下这个“向后兼容”,如下:

也就意味着在List接口中带了一个排序的功能了,那假设不是以这种默认方法的形式来提供的话【也就是将sort()方法声明为抽象的】,那么对于以前使用了List接口的代码那就会造成破坏性的影响,为什么?可以想象一样对于一个稳定的老系统当从Java的低版本升级到了Java8之后,发现List接口中多出了一个sort()抽象方法,那不得对稳定的老系统修改代码来保证可以兼容Java8,那这种设计是完全不合理的,合理的设计应该是当一个系统Java由低版本升到高版本之后应该是完全可以正常编译运行的,那么默认方法的出现就完全可以解决这样向后兼容的问题了,因为它是具体实现所以也不会使用者强制去重写里面的代码,对于老版本系统而言也无需做任何的代码变更,所以光知道默认方法是个什么东东这个不是重点,重点是要体会为啥要提出默认方法这个东东。
Stream介绍与操作方式:
关于Stream在之前的学习中也已经初步涉及到了,如下:

只是木有系统的学习,接下来就系统的对它进行了解,Stream是在Java8中与Lambda表达式相伴相生的一个极其重要的概念,通过流的方式可以让我们更好的操作集合,而且以函数式、更加流畅、更加语义化的来让我们去操作流,而流中会大量的使用到咱们之前学习的函数式接口,我们知道在Java8中函数式接口都位为java.util.function包中,而对于流则全位于java.util.stream包中,如下:

展开流包看一下:
AbstractPipeline
AbstractShortCircuitTask
AbstractSpinedBuffer
AbstractTask
BaseStream
Collector
Collectors
DistinctOps
DoublePipeline
DoubleStream
FindOps
ForEachOps
IntPipeline
IntStream
LongPipeline
LongStream
MatchOps
Node
Nodes
PipelineHelper
ReduceOps
ReferencePipeline
Sink
SliceOps
SortedOps
SpinedBuffer
Stream
StreamOpFlag
Streams
StreamShape
StreamSpliterators
StreamSupport
TerminalOp
TerminalSink
Tripwire
可以看到非常之多,当然不可能一一学到,这里跟函数式接口的学习方法类似,只学重要的,当重要的都掌握了之后,其它的就触类旁通啦,另外Stream是流中最重要的基础,如标红所示,所以接下来先学它,打开它查看一下它里面的方法,大多数是高阶函数【具体什么是高阶函数可以参考:http://www.cnblogs.com/webor2006/p/8193855.html】:

接下来读一下它的javadoc:


接着看官方对这个示例的解释:




说到pipeline,其实跟Linux的管道的概念很像,管道是将多个操作连接在一起,使得多个简单的操作最后形成一个功能非常强大的操作。


这个说明比较重要,说明了流操作的构成,这里先有个印象,之后还会再解释。

根据这段关键的说明可以对流进行一个总结:
1、流由三部份组成:
①、源;
②、零个或多个中间操作;
③、终止操作;
2、流操作的分类:
①、惰性求值;
②、及早求值;
怎么理解上面列的总结呢?其中"惰性求值"实际上就是指的"零个或多个中间操作","及早求值"指的是"终止操作",比如说有这样一个流操作:
"stream.xxx().yyy().zzz().count();",其中stream为流所对应的源,而xxx().yyy().zzz()则为中间操作,它们就是惰性求值的;而count()则为终止操作,它是及早求值的。惰性顾名思义就是比较懒惰的,如果没有终止操作它们是不会立马执行的,也就是说"stream.xxx().yyy().zzz()"这句话因为没有终止操作啥都不会执行,这就证明确实是懒性滴,而只要有了终止操作count(),那中间操作才会进行执行,而且是立即执行,并且流操作中只有一个终止操作,目前没有代码的描述可能比较抽象,有个印象既可。
流的创建:
接下来编写代码来领略一下流的使用,首先看一下如何创建一个流:

而其中看一下of()方法的定义:

接下通过数组创建,如下:

这两种其本质上是一样的,都是调用of()方法来创建。
接下来继续用第三种方式创建:

其实这种方式跟第一种的本质还是一样的,为什么?

最后再看一下最常用的创建流的方式,如下:

流的使用:
接下来具体使用一下流,看能给咱们带来哪些便利性:


编译运行:

为啥是包含了3,但是不包含8呢?看下range()的具体实现:

另外从这个例子中有木有体会到使用了Stream之后的便捷性,如果照传统的方式生成那得弄一个循环了,而使用了Stream之后一句话搞定。
那如果也想包含后面的元素呢?其实也有现成的方法,如下:

其看一下该方法的参数名就可以知晓确实是包含结束元素:

接下来用Stream来实现如下场景:有一个整形类型的List,然后对List中的每一个元素x2,然后再将所有的乘2的元素求和输出出来。传统的实现方式肯定得要遍历去实现,这里就不演示了,直接采用新的方式来写:

接着就是需要对其元素进行求和了,那怎么做呢?这时得用到reduce()了,如下:

其中第一个参数identity为初始累加值,这里当然传0啦,第二个参数为BinaryOperator,这个函数式接口咱们之前已经学习过了,回顾下它的函数原型:

而在Integer类中对于两数求和的函数刚好满足这个函数式接口的要求,看:

所以其最终的写法如下:

可见用流的方式实现是何等的清晰简单,而且语义上也更好理解,针对这个流操作,再来复习一下它的组成部分:

java8学习之Stream介绍与操作方式详解的更多相关文章
- java8学习之Stream分组与分区详解
Stream应用: 继续举例来操练Stream,对于下面这两个集合: 需求是:将这两个集合组合起来,形成对各自人员打招呼的结果,输出的结果如: "Hi zhangsan".&quo ...
- 2020你还不会Java8新特性?方法引用详解及Stream 流介绍和操作方式详解(三)
方法引用详解 方法引用: method reference 方法引用实际上是Lambda表达式的一种语法糖 我们可以将方法引用看作是一个「函数指针」,function pointer 方法引用共分为4 ...
- Java 8系列之Stream的基本语法详解
本文转至:https://blog.csdn.net/io_field/article/details/54971761 Stream系列: Java 8系列之Stream的基本语法详解 Java 8 ...
- ASP.NET MVC 5 学习教程:生成的代码详解
原文 ASP.NET MVC 5 学习教程:生成的代码详解 起飞网 ASP.NET MVC 5 学习教程目录: 添加控制器 添加视图 修改视图和布局页 控制器传递数据给视图 添加模型 创建连接字符串 ...
- Nginx的介绍和安装详解
[介绍+安装]Nginx的介绍和安装详解 == 介绍和安装 == Nginx是一个自由.开源.高性能及轻量级的HTTP服务器及反转代理服务器, 其性能与IMAP/POP3代理服务器相当.Nginx ...
- 零拷贝详解 Java NIO学习笔记四(零拷贝详解)
转 https://blog.csdn.net/u013096088/article/details/79122671 Java NIO学习笔记四(零拷贝详解) 2018年01月21日 20:20:5 ...
- Docker学习(六)——Dockerfile文件详解
Docker学习(六)--Dockerfile文件详解 一.环境介绍 1.Dockerfile中所用的所有文件一定要和Dockerfile文件在同一级父目录下,可以为Dockerfile父目录的子目录 ...
- IP地址和子网划分学习笔记之《IP地址详解》
2018-05-03 18:47:37 在学习IP地址和子网划分前,必须对进制计数有一定了解,尤其是二进制和十进制之间的相互转换,对于我们掌握IP地址和子网的划分非常有帮助,可参看如下目录详文. ...
- OpenCV学习C++接口 Mat像素遍历详解
OpenCV学习C++接口 Mat像素遍历详解
随机推荐
- python3 速查参考- python基础 9 -> MySQL基础概念、数据库create、alter、insert、update、delete、select等基础命令
前置步骤: 下载一个绿色版的mysql数据库客户端连接工具 :http://wosn.net/821.html mysql平台为win7(以后会有CentOS上的) 学习目的: 掌握数据库的基本概念, ...
- 【并行计算-CUDA开发】有关CUDA当中global memory如何实现合并访问跟内存对齐相关的问题
ps:这是英伟达二面面的一道相关CUDA的题目.<NVIDIA CUDA编程指南>第57页开始 在合并访问这里,不要跟shared memory的bank conflic ...
- 论文阅读 | Adversarial Example Generation with Syntactically Controlled Paraphrase Networks
[pdf] [code] 句法控制释义网络 SCPNS 生成对抗样本 我们提出了句法控制意译网络(SCPNs),并利用它们来生成对抗性的例子.给定一个句子和一个目标语法形式(例如,一个选区解析),s ...
- XSS练习平台-XSS Challenges
XSS Challenges http://xss-quiz.int21h.jp/ XSS基础不好的建议优先查看 关于XSS中使用到的html编码 js编码各种场景用法 http://su.xmd ...
- [Agc036C]Triangle_数学
Triangle 题目链接:https://atcoder.jp/contests/agc036/tasks/agc036_a 题解: 我开始的时候以为是$Millar-Rabin$加$Pollard ...
- centos 7 cloudera-manager5.16.2,CDH5.16.2安装升级spark2.4.0
1.在已经安装好系统的linux服务器上关闭selinux和iptables 2.在所有linux服务器上配置ntp服务并设置ntp时间同步 3.在所有linux服务器上安装好cm和cdh版本所需要对 ...
- 将本地镜像上传到Docker镜像仓库
⒈在Docker Hub(Docker官方镜像仓库)注册自己的用户名. ⒉在Docker中使用docker login命令登录自己的用户名密码. ⒊使用docker push 镜像名称 上传本地镜像到 ...
- 结对编程-如何用精简的java代码写出这个系统
[写在前面]这篇博客是软件工程这门课中要求结对编程.规则是这样的:结对的两个人,分别看对方个人项目代码,2天时间内,分析对方代码优点和缺点.我是来分析凌嘉文同学的代码. 先写一下个人项目中的项目需求, ...
- 【问题】【编程环境】fatal error: security/pam_appl.h
[问题] 今天在docker中基于centos镜像的容器编译gogs遇到错误 似乎缺少库文件 [解决] yum -y install pam-devel
- Python开发之IDE选择
Python开发之IDE 一.为什么用IDE 到现在为止,谁还不是个写过代码的人啦,但你有没有发现,每次写代码要新建文件.写完保存时还要选择存放地点,执行时还要切换到命令行调用python解释器,好麻 ...