收集器用法详解:

在上次已经系统的阅读了Collector收集器的Javadoc对它已经有一个比较详细的认知了,但是!!!它毕境是只是一个接口,要使用的话还得用它的实现类,所以在Java8中有它进行了实现,而且也只有唯一的一个实现,其实现类名叫:CollectorImpl,它在咱们已经使用过N次的Collectors类中,如下:

其把它的完整代码贴出来,如下:

/**
* Simple implementation class for {@code Collector}.
*
* @param <T> the type of elements to be collected
* @param <R> the type of the result
*/
static class CollectorImpl<T, A, R> implements Collector<T, A, R> {
private final Supplier<A> supplier;
private final BiConsumer<A, T> accumulator;
private final BinaryOperator<A> combiner;
private final Function<A, R> finisher;
private final Set<Characteristics> characteristics; CollectorImpl(Supplier<A> supplier,
BiConsumer<A, T> accumulator,
BinaryOperator<A> combiner,
Function<A,R> finisher,
Set<Characteristics> characteristics) {
this.supplier = supplier;
this.accumulator = accumulator;
this.combiner = combiner;
this.finisher = finisher;
this.characteristics = characteristics;
} CollectorImpl(Supplier<A> supplier,
BiConsumer<A, T> accumulator,
BinaryOperator<A> combiner,
Set<Characteristics> characteristics) {
this(supplier, accumulator, combiner, castingIdentity(), characteristics);
} @Override
public BiConsumer<A, T> accumulator() {
return accumulator;
} @Override
public Supplier<A> supplier() {
return supplier;
} @Override
public BinaryOperator<A> combiner() {
return combiner;
} @Override
public Function<A, R> finisher() {
return finisher;
} @Override
public Set<Characteristics> characteristics() {
return characteristics;
}
}

貌似相当简单呀,细看一下它的具体实现:

那思考一个问题:为什么该实现类被设计成了“static class” 静态内部类而不新做为一个类的文件存在呢?其实也不难理解,因为Collectors类类似一个工厂类来给开发者提供非常常见的Collector的实现,如:counting、minBy、maxBy、summingInt()、groupingBy等等,从它的构造设计就可以得知:

而由于每个方法都是完全依赖于Collector的具体实现CollectorImpl,如下:

因此直接将CollectorImpl就放到了Collectors类的里面了,只供它使用,其它类是不会使用CollectorImpl类的。

既然已经将源代码定格在了Collectors了,何不读一下它的javadoc呢?

那如果这里面提供的满足不了咱们的实际业务需求那怎么办呢?这时只能自己实现了,这个在未来会学习到,这里先抛出这个东东。

多级分组和分区:

接下来则用例子再一次加深对Collectors提供的核心方法的了解,继续用上一次【http://www.cnblogs.com/webor2006/p/8310369.html】已经使用过的例子如下:

下面以各种需求来展开代码实践:

①、从学生集合中找出来分数最低的那个学生,并将其学生实体打印出来。

那此时它返回的是一个什么类型的数据呢?

既然是返回的Optional,根据它的最佳实践得这样写:

那如果查询成绩最高的学生呢,依葫芦画瓢嘛:

那如果求平均值呢?so easy:

那请问下该计算最后返回的结果类型是?还是OptionInt么?很显然不是了,因为平均值默认就是0嘛,没有元素最终也会返回0,所以需要注意一下,下面打印一下:

接着求出分数的总合呢?

接着求出摘要信息,就是说可以看到求和,求平均的信息,之前也用过了,这里再复习一下:

②、将学生的名字拼接到一起输出出来:

接着连接时以","进行分割:

编译运行:

然后再进一步,给拼接的字符串加前后缀,如下:

编译运行:

③、groupingBy()和partitioningBy()拓展:

之前咱们已经用过这两个方法了,只是说当时只是一级分组,如下:

实际上这两个方法是可以支持多级分组和分区的,所以下面来使用一下,为了更好的表达,下面给集合中再增加一个学生数据:

然后先对学生的分数进行分组,这时如果一个组里有多个学生的话,再按学生的名字进行分组,那如何实现呢,看下面:

那请问该结果返回啥子类型?下面看下:

下面看下结果:

{80={zhangsan=[Student{name='zhangsan', score=80}]}, 100={wangwu=[Student{name='wangwu', score=100}]}, 90={lisi=[Student{name='lisi', score=90}], zhaoliu=[Student{name='zhaoliu', score=90}, Student{name='zhaoliu', score=90}]}}

接下来再来看一下分区,找出成绩大于80的学生在一个分区,以及小于80的学生在一个分区,比较简单,因为之前已经练过了,直接看代码:

{false=[Student{name='zhangsan', score=80}], true=[Student{name='lisi', score=90}, Student{name='wangwu', score=100}, Student{name='zhaoliu', score=90}, Student{name='zhaoliu', score=90}]}

继续,这次先对成绩是否大于80进行分区,接着再对分区之后的集合里面再对成绩是否大于90再一次进行分区,如何整呢?

那请问它的结果返回的类型是啥?下面看下:

{false={false=[Student{name='zhangsan', score=80}], true=[]}, true={false=[Student{name='lisi', score=90}, Student{name='zhaoliu', score=90}, Student{name='zhaoliu', score=90}], true=[Student{name='wangwu', score=100}]}}

那通过上面两个可以嵌套分区或分组是要说明一个什么问题呢?说明Collector设计成可组合的,也就是Collector时面还是可嵌套Collector,这个在Collector的javadoc上也进行了说明,如下:

接着进一步:除了分组里面可以继续分组、分区里面可以继续分区之外,在分组里面还可以用其它的一个Collector,下面看一个这样的例子:统计分数大于80的学生,然后进行分组,然后再计算每个组的一个总数量,看下面的做法:

下面继续变更需求:先根据学生的名字进行分组,然后得到组里学生分数最小的那个,具体做法如下:

那此时看它返回的结果类型:

但是!!这不是我们所期望的结果呀,对于有分组的元素肯定是不可能为空的,也就是只要有分组肯定里面的元素就一定有最小的学生,等于这个返回Optional对于咱们这个场景有点多余,那如何只返回Map<String,Student>这个类型而不返回Optional呢?简单能想到的方法当然是通过遍历这个结果然后再通过Optional.ifPresent()方法将其拿出来喽,但是!!实际有另外一个简单的办法,如何做呢?

编译运行:

{lisi=Student{name='lisi', score=90}, zhaoliu=Student{name='zhaoliu', score=90}, zhangsan=Student{name='zhangsan', score=80}, wangwu=Student{name='wangwu', score=100}}

从collectingAndThen这个方法的见名之义就可以知道它是先收集,收集完之后则干某件事,好好体会一下这种场景的这种用法。

java8学习之收集器用法详解与多级分组和分区的更多相关文章

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

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

  2. jQuery学习笔记之Ajax用法详解

    这篇文章主要介绍了jQuery学习笔记之Ajax用法,结合实例形式较为详细的分析总结了jQuery中ajax的相关使用技巧,包括ajax请求.载入.处理.传递等,需要的朋友可以参考下 本文实例讲述了j ...

  3. C++学习笔记之pimpl用法详解

    原文链接:https://www.jb51.net/article/122557.htm 在编写稳定代码是,管理好代码间的依赖性是不可缺少的一个环节.特别是库文件的编写中,减少代码间的依赖性可以提供一 ...

  4. (高级篇)jQuery学习之jQuery Ajax用法详解

    jQuery Ajax在web应用开发中很常用,它主要包括有ajax,get,post,load,getscript等等这几种常用无刷新操作方法,下面我来给各位同学介绍介绍. 我们先从最简单的方法看起 ...

  5. jQuery学习之jQuery Ajax用法详解

    jQuery Ajax在web应用开发中很常用,它主要包括有ajax,get,post,load,getscript等等这几种常用无刷新操作方法,下面我来给各位同学介绍介绍. 我们先从最简单的方法看起 ...

  6. jQuery学习之jQuery Ajax用法详解(转)

    [导读] jQuery Ajax在web应用开发中很常用,它主要包括有ajax,get,post,load,getscript等等这几种常用无刷新操作方法,下面我来给各位同学介绍介绍.我们先从最简单的 ...

  7. jQuery学习之jQuery Ajax用法详解(转)

    jQuery Ajax在web应用开发中很常用,它主要包括有ajax,get,post,load,getscript等等这几种常用无刷新操作方法,下面我来给各位同学介绍介绍. 我们先从最简单的方法看起 ...

  8. 2020了你还不会Java8新特性?(五)收集器比较器用法详解及源码剖析

    收集器用法详解与多级分组和分区 为什么在collectors类中定义一个静态内部类? static class CollectorImpl<T, A, R> implements Coll ...

  9. STL pair 常见用法详解

    <算法笔记>学习笔记 pair 常见用法详解 //pair是一个很实用的"小玩意",当想要将两个元素绑在一起作为一个合成元素, //又不想因此定义结构体时,使用pair ...

随机推荐

  1. 2019.06.05 ABAP EXCEL 操作类代码 OLE方式(模板下载,excel上传,内表下载)

    一般使用标准的excel导入方法9999行,修改了标准的excel导入FM 整合出类:excel的 模板下载,excel上传,ALV内表下载功能. 在项目一开始可以SE24创建一个类来供整体开发使用, ...

  2. 面向对象编程(oop)的变迁

    作者:匿名用户链接:https://www.zhihu.com/question/34018003/answer/132740170来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请 ...

  3. Qt QLabel添加cliked事件

    #ifndef MYLABEL_H #define MYLABEL_H #include <QObject> #include <QLabel> class MyLabel : ...

  4. linux下mysql设置主从

    一  主服务器修改 mysql的主从设置主要原理是 主数据库开启日志,并且创建从服务器专属账户,从服务器用该账户,读取到日志进行同步 准备两个mysql数据库(如何安装请查看,linux下mysql安 ...

  5. QT5中编译存在的几个问题(LNK2019,构造函数不能有返回类型)

    1. 自己构造新类,注意必须在头文件最后加上分号 写个c++类报“构造函数不能有返回类型”, 谷歌一下,才找到原因: 原来是我定义的类后面没有用“:”结尾,构造函数默认把整个类作为返回值了 2. 新建 ...

  6. 【POJ - 3279】Fliptile(经典翻转问题)

    -->Fliptile 直接中文翻译:Descriptions: 给你一个01矩阵,矩阵大小为M x N.(1 <= M , N <= 15)每次操作选择一个格子,使得该格子与上下左 ...

  7. bert系列一:《Attention is all you need》论文解读

    论文创新点: 多头注意力 transformer模型 Transformer模型 上图为模型结构,左边为encoder,右边为decoder,各有N=6个相同的堆叠. encoder 先对inputs ...

  8. Laravel 里最简单的CURD套路

    控制器 namespace App\Http\Controllers; use App\Http\Requests\UserAddressRequest; use App\Models\UserAdd ...

  9. 多标签分类(multi-label classification)综述

    意义 网络新闻往往含有丰富的语义,一篇文章既可以属于“经济”也可以属于“文化”.给网络新闻打多标签可以更好地反应文章的真实意义,方便日后的分类和使用. 难点 (1)类标数量不确定,有些样本可能只有一个 ...

  10. 小菜鸟之JAVA面试题库1

    四次挥手 客户端发送释放连接报文,关闭客户端到服务端的数据传输 服务端收到后,发送确认报文给客户端 服务端发送释放连接报文,关闭服务端到客户端的数据传输 客户端发送一个确认报文给服务端 ------- ...