java8学习之Collectors工厂类源码分析与实战
如上一节【http://www.cnblogs.com/webor2006/p/8360232.html】在结尾处谈到的,彻底理解了Collector收集器之后,有必要对其系统Collectors实现的各种非常常见的收集器进行仔细阅读,所以这也是接下来要去完成的,下面开始。
对于Collectors类而言,它是一个工厂类,因为它的构造是一个私的有,如下:

而对于这个类中有一个静态类去实现Collector接口,这个也已经在之前详细分析过了,如下:

而对于它里面的各种实现基本可以分为两种情况:
1、通过CollectorImpl来实现,如:

2、通过reducing方法来实现,而reducting方法本身又是通过CollectorImpl来实现的,也就是说CollectorImpl是核心,如:

下面则开始一个个具体方法分析:
Collectors.toList():
这个是咱们使用最多的一个方法啦,其实现也比较容易搞懂(前提是自己对收集器原理理解得非常透彻了),下面看一下:

而其实上面的这种强制转换的方式还可以写成它:ArrayList<T>::new。
接着第二个参数是“BiConsumer<A, T> accumulator”累加器,而该方法的实现如下:

而第三个参数是“BinaryOperator<A> combiner”,将多个结果容器合并成一个,实现如下:

最后一个参数为:“Set<Characteristics> characteristics”,也就是收集器的特性,这里实现是直接传的一个常量,如下:


Collectors.toCollection():
对于toList()中间结果类型生成的就是ArrayList类型,如下:

所以方法不需要任何参数,而想要换成其它的结果容器类型那么这个方法就派上用场啦,它是一个更加通用的方法, 当然具体的容器类型可以由咱们调用方来指定了,如下:

所以此时对于收集器的第一个参数直接就传的是咱们进来的这个参数了:

其它的参数其本上跟toList()实现类似,所以就不啰嗦啦,真的是如果知道了如何自己来自定义一个收集器,对于这些系统的实现看着是非常之亲切的。
Collectors.toSet():
基本上跟toList()的实现类似,第一个参数实例化结果容器,这里传的是HashSet,如下:

第二个参数如下:

第三个参数跟上面的方法实现一样,不多解释了,最后看一下第四个特性参数,这次的跟上面两个方法不一样了,下面看下:


Collectors.joining():
该方法的作用是将集合中的元素进行字符串连接,之前也用它做过一些例子,下面看下它的具体实现:
首先看一下传的泛型类型:

可以看到中间结果类型和最终结果类型是不一样的,所以可以看到它实际上是调用CollectorImpl类带有五个参数的构造函数,如下:

相比上面的方法,多了一个finisher参数,为什么?因为中间结果类型跟最终结果类型不是同一个类型,所以需要通过调用finisher()方法对其进行类型转换嘛,好了,下面具体看一下参数是如何生成的:




最后参数这次的特性又不同了,分析下:


接下来joining()还有以下两个方法重载,其中第二个joining()是调用最后一个joining方法来实现的,如下:

所以将注意力就集中到最后一个joining()方法之上喽:
第一个参数实始化一个中间结果容器,这里采用了一个在Java1.8中提供的一个辅助类StringJoiner,它主要是用于字符串拼接的,如下:


第二个参数为累加器,如下:


第三个参数为中间结果合并:


第四个参数则是生成结果,如下:

最后一个特性也是无特性:

Collectors.mapping():
下面先来看一下该方法的javadoc对它的说明:


那啥叫"downstream"呢?可以瞅一下mapping()函数的方法定义:


下面来看一下它的具体实现:除了第二个参数不一样之外,其它参数都是使用的downstream的相应的方法,如下:

而焦点就定格到了第二个参数:元素累加器,也是mapping()实现的核心,其实也是用的下流的收集器做了一定的转换,下面具体来分析一下是如何达到转换的目的的:


所以在javadoc上对应于这句话:

Collectors.collectingAndThen():
先看一下它的javadoc:

接下来看一下它的具体实现:



也就是这个整个判断语句就是将"IDENTITY_FINISH"的特性去掉了,那为啥要去掉这个特性呢?其实很容易想到,因为该函数是必须要执行finisher()方法的,而如果设置有"IDENTITY_FINISH"特性则不会执行这个finisher()方法了。所以再看下面的返回:

而andThen()就是Function里面提供的方法,这个咱们之前也已经学习过了,如下:

Collectors.counting():

而这里粗略的看一下reducing()方法的参数:

根据传给reducing()方法的值,第一个参数为初始值为0;第二个参数则是将无素都转换成1,第三个则是进行元素的累加,因为所有元素值都变为1了,那总和既为元素的总个数。关于reducing()的具体实现分析放到下一次,这里有个初步印象既可。
Collectors.minBy()&Collectors.maxBy():

Collectors.summingInt():
这个收集器是用来对元素进行求和用的,下面来看一下它的具体实现:



实现是比较容易读懂的,但是有个疑问:为啥要生成一个长度为1的数组呢?最终不就是需要一个int的结果,直接生成一个int类型不就可以了,因为第一个参数是需要一个可变的结果容器,而单纯一个数字当然不是一个容器啦,另外数字是没法传递的,因为它是不可变的,所以这就是为啥要生成一个长度为1的数组的原因了。
类似的还有summingLong()、summingDouble(),这里就不再多说了。
Collectors.averagingInt():
这个是用来求平均值的,而平均值很显然是用总数除以个数,所以看一下它的实现:




其中类似的还有averagingLong()、averagingDouble(),这里也不多说了。
java8学习之Collectors工厂类源码分析与实战的更多相关文章
- java8学习之groupingByConcurrent与partioningBy源码分析
在上一次[http://www.cnblogs.com/webor2006/p/8387656.html]中对于Collectors.groupingBy()方法进行了完整的分析之后,接着继续来分析一 ...
- List 接口以及实现类和相关类源码分析
List 接口以及实现类和相关类源码分析 List接口分析 接口描述 用户可以对列表进行随机的读取(get),插入(add),删除(remove),修改(set),也可批量增加(addAll),删除( ...
- Cocos2d-X3.0 刨根问底(六)----- 调度器Scheduler类源码分析
上一章,我们分析Node类的源码,在Node类里面耦合了一个 Scheduler 类的对象,这章我们就来剖析Cocos2d-x的调度器 Scheduler 类的源码,从源码中去了解它的实现与应用方法. ...
- Java Properties类源码分析
一.Properties类介绍 java.util.Properties继承自java.util.Hashtable,从jdk1.1版本开始,Properties的实现基本上就没有什么大的变动.从ht ...
- Java显式锁学习总结之六:Condition源码分析
概述 先来回顾一下java中的等待/通知机制 我们有时会遇到这样的场景:线程A执行到某个点的时候,因为某个条件condition不满足,需要线程A暂停:等到线程B修改了条件condition,使con ...
- java中List接口的实现类 ArrayList,LinkedList,Vector 的区别 list实现类源码分析
java面试中经常被问到list常用的类以及内部实现机制,平时开发也经常用到list集合类,因此做一个源码级别的分析和比较之间的差异. 首先看一下List接口的的继承关系: list接口继承Colle ...
- Java并发编程笔记之Unsafe类和LockSupport类源码分析
一.Unsafe类的源码分析 JDK的rt.jar包中的Unsafe类提供了硬件级别的原子操作,Unsafe里面的方法都是native方法,通过使用JNI的方式来访问本地C++实现库. rt.jar ...
- Java显式锁学习总结之五:ReentrantReadWriteLock源码分析
概述 我们在介绍AbstractQueuedSynchronizer的时候介绍过,AQS支持独占式同步状态获取/释放.共享式同步状态获取/释放两种模式,对应的典型应用分别是ReentrantLock和 ...
- Redis学习之zskiplist跳跃表源码分析
跳跃表的定义 跳跃表是一种有序数据结构,它通过在每个结点中维持多个指向其他结点的指针,从而达到快速访问其他结点的目的 跳跃表的结构 关于跳跃表的学习请参考:https://www.jianshu.co ...
随机推荐
- Django与Session
Session Session的由来 Cookie虽然在一定程度上解决了"保持状态"的需求,但是由于Cookie本身最大支持4096字节,以及Cookie本身保存在客户端,可能 ...
- 【AMAD】jsonschema -- (又)一个JSON Schema的Python实现
动机 简介 用法 个人评分 动机 JSON Schema1是一个专业词汇,可以让你注解和验证JSON文档. 使用JSON Schema的好处有: 描述你的数据格式 提供清晰的易读的文档 验证数据: 用 ...
- Python 课件笔记
Python 3.0 课件笔记 我们需要做的就是认真听取每一堂课,私下阅读老师博客笔记进行再复习,综合理解后写下自己的笔记,加深印象! Day1 - Python基础1 介绍.基本语法.流程控制
- ORACLE 左连接 右连接 内连接 外连接 全连接 五中表连接方式
1.左连接 :left join 2.右连接:right join 3.内连接:inner join 4.外连接:outer join 5.全连接:full join
- python r r+;w w+;a a+;以及加不加b区别
#以下内容均在正常打开文件的情况下运行 一.列表格 模式 可做操作 若文件不存在 是否覆盖 r 只能读 报错 --- r+ 可读可写 报错 是 w 只能写 创建 是 w+ 可读可写 创建 是 a 只能 ...
- [转帖]FreeBSD、OpenBSD、NetBSD的区别
FreeBSD.OpenBSD.NetBSD的区别 Linux 的历史 http://www.361way.com/unix-bsd/1513.html 一直unix在我心目中的地位都很高,uni ...
- 算法 - k-means++
Kmeans++算法 Kmeans++算法,主要可以解决初始中心的选择问题,不可解决k的个数问题. Kmeans++主要思想是选择的初始聚类中心要尽量的远. 做法: 1. 在输入的数据点中随机选 ...
- Centos7 更换为网易YUM源
当我们刚刚安装系统的时候 yum 的速度那是真滴慢所以我们就需要一个更加快速的镜像,这时候网易镜像带给我们便捷.下面来一起更换吧! 备份当前的 yum 源 # yum 源在目录 /etc/yum.re ...
- java-阿里云发送短信
<!--aliyun短信sdk--> <dependency> <groupId>com.aliyun</groupId> <artifactId ...
- nginx+gunicorn/uwsgi+python web 的前世今生
我们在部署 flask.django 等 python web 框架时,网上最多的教程就是 nginx+gunicorn/uwsgi 的部署方式,那为什么要这么部署呢,本文就来系统地解释这个问题. 必 ...