关于默认方法【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介绍与操作方式详解的更多相关文章

  1. java8学习之Stream分组与分区详解

    Stream应用: 继续举例来操练Stream,对于下面这两个集合: 需求是:将这两个集合组合起来,形成对各自人员打招呼的结果,输出的结果如: "Hi zhangsan".&quo ...

  2. 2020你还不会Java8新特性?方法引用详解及Stream 流介绍和操作方式详解(三)

    方法引用详解 方法引用: method reference 方法引用实际上是Lambda表达式的一种语法糖 我们可以将方法引用看作是一个「函数指针」,function pointer 方法引用共分为4 ...

  3. Java 8系列之Stream的基本语法详解

    本文转至:https://blog.csdn.net/io_field/article/details/54971761 Stream系列: Java 8系列之Stream的基本语法详解 Java 8 ...

  4. ASP.NET MVC 5 学习教程:生成的代码详解

    原文 ASP.NET MVC 5 学习教程:生成的代码详解 起飞网 ASP.NET MVC 5 学习教程目录: 添加控制器 添加视图 修改视图和布局页 控制器传递数据给视图 添加模型 创建连接字符串 ...

  5. Nginx的介绍和安装详解

    [介绍+安装]Nginx的介绍和安装详解   == 介绍和安装 == Nginx是一个自由.开源.高性能及轻量级的HTTP服务器及反转代理服务器, 其性能与IMAP/POP3代理服务器相当.Nginx ...

  6. 零拷贝详解 Java NIO学习笔记四(零拷贝详解)

    转 https://blog.csdn.net/u013096088/article/details/79122671 Java NIO学习笔记四(零拷贝详解) 2018年01月21日 20:20:5 ...

  7. Docker学习(六)——Dockerfile文件详解

    Docker学习(六)--Dockerfile文件详解 一.环境介绍 1.Dockerfile中所用的所有文件一定要和Dockerfile文件在同一级父目录下,可以为Dockerfile父目录的子目录 ...

  8. IP地址和子网划分学习笔记之《IP地址详解》

    2018-05-03 18:47:37   在学习IP地址和子网划分前,必须对进制计数有一定了解,尤其是二进制和十进制之间的相互转换,对于我们掌握IP地址和子网的划分非常有帮助,可参看如下目录详文. ...

  9. OpenCV学习C++接口 Mat像素遍历详解

    OpenCV学习C++接口 Mat像素遍历详解

随机推荐

  1. Jmeter接口测试 2=> Jmeter工具的介绍

    第一节 接口测试流程 参数化:EXCEl文件参数化.数据库参数化.直接代码中配置.配置文件 预处理请求(前置处理):对请求的参数进行预处理.准备,如加密数据.组织测试数据 发起请求:httpclien ...

  2. flask 之(七) --- 认证|文件|部署

    登陆注册 说明: 令牌Token认证,在对HTTP形式的API发请求时,大部分情况我们不是通过用户名密码做验证,而是通过一个令牌[Token来做验证]. RESTful API无法使用Flask-Lo ...

  3. kubeadm安装集群系列(kubeadm 1.15.1)

    kubeadm已经进入GA阶段,所以尝试使用kubeadm从零开始安装高可用的Kubernetes集群,并记录下过程和所有坑 本文基于kubeadm 1.15.1 目录 kubeadm安装集群系列-1 ...

  4. BiGAN的复现

    数据集是10000个样本,前8000个训练集,后面的用来测试.每个样本是1*144(重构成12*12的矩阵),将原始BiGAN有编码器.判别器和生成器,将里面的全连接层全部替换成了卷积. from _ ...

  5. HDFS之JAVAAPI

    JAVAAPI 上传小文件 代码

  6. Nginx 配置文件解释及简单配置

    Nginx配置文件大致分为以下几个块 1.全局块:配置影响nginx全局的指令.一般有运行nginx服务器的用户组,nginx进程pid存放路径,日志存放路径,配置文件引入,允许生成worker pr ...

  7. OpenResty + Lua访问Redis,实现高并发访问时的毫秒级响应打回

    一.lua中redis的配置依赖: 1.OpenResty的lua访问redis的插件:https://github.com/openresty/lua-resty-redis 二.下载后,导入对应的 ...

  8. (企业面试)描述Linux系统的启动过程?

    1简单描述(口头): 1.开机BIOS自检(检查硬件,cpu,主板,内存……) 2. MBR引导 硬盘 0 柱面 0 磁道 1 扇区的前446byte 3.  grub 引导菜单 cat/etc/gr ...

  9. 算法flink

    和Yarn-Cluster模式不同,Session模式的资源在启动Yarn-Session时候就已经启动了,后续提交的作业全都在已申请的资源空间内运行,比较适合小而多的作业 # 启动yarn-sess ...

  10. java中的 |=、&=、^=

    |=  关于 |= 运算符:|= 运算符和 += 这一类的运算符一样,拆解开就是 a = a | b: 代码如下: public static strictfp void main(String[] ...