自定义收集器深度剖析:

在上次【http://www.cnblogs.com/webor2006/p/8342427.html】中咱们自定义了一个收集器,这对如何使用收集器Collector是极有帮助的,这次基于它再来进一步,争取彻底理解收集器的所有概念,这里再定义一个新的收集器,其实现如下需求:

对于一个Set<String>这样一个集合,通过收集器将其转换成Map<String,String>,比如对于["hello", "world", "hello world"]这个Set集合,最后通过咱们的收集器要输出成:[{"hello", "hello"}, {"world", "world"}, {"hello world", "hello world"}]。

下面先来新建一个类,然后实现Collector接口:

接下来重写Collector的五个关键方法:

接下来具体来一个个实现:

supplier():

比较简单,就是创建一个中间累加结果容器,这里是用的HashSet,如下:

accumulator():

这个也比较简单,返回的BiConsumer对象中的第一个参数表示中间累加的结果容器,第二个参数表示下一个要累加的元素,所以:

combiner():

这个合并方法是针对并行流的,串行流是不会调用它的,其需要的BinaryOperator的两个参数都是Set<T>类型的,具体实现如下:

finisher():

这个方法的回调需要依赖于收集器的特性,如果设置了IDENTITY_FINISH这个特性那此回调则不会调用了,这次中间结果容器类型(Set<T>)跟最终结果的类型(Map<T,T>)很明显是不一样的,所以此方法针对咱们这个例子一定得要调用,不然就会有问题,具体实现如下:

characteristics():

这里先只加上一个无序的特性,因为咱们用的是Set嘛,显然就是无序的:

至此收集器就已经定义完啦,接下来就来使用一下下喽~先构造一个集合:

接着咱们自定义的这个收集器来将Set<String>转换成Map<String, String>,如下:

其结果如预期,其中看一下日志输出这块的打印:

接下来咱们就要来改造程序啦,用来彻底搞明白收集器里面的一些关系,首先先看一下这个特性:

咱们如果给收集器加上上面这个特性,那会有什么现象呢?下面试下:

这里解释其原因从读这个特性的介绍开始:

那它具体是在哪里进行转换的呢?其实上一节中也进行说明过,在这:

所以说只要设置了"IDENTITY_FINISH"这个特性,则编译器就认为收集器的中间结果和最终结果的类型是一模一样的,则直接强转,在实际使用时需要根据实际的场景来正确的设置相应的特性,当然啦正确设置特性的前提是你对这里面的每个特性枚举值的具体含义彻底理解才行,所以通过这个实验咱们就对这个Characteristics.IDENTITY_FINISH特性彻底理解了。

接下来咱们将结果放到一个TreeMap()中,这样收集的结果就是带排序的了:

并行流陷阱:

接下来则将程序改造成一个并行流,不过在改并行流之前先来看一下串行流的线程情况,这里先在accumulator()函数中打印一下线程的名字,如下:

接下来则改用并行流,再来看一下输出:

接下来咱们再来修改一下日志输出语句,如下:

既然是并行流,那完全可以给收集器加一个并行的特性啦,所以说干就干:

貌似也没啥区别,都正常打印了嘛,接下来再次运行,会出现如下异常:

目前单个运行这种异常显现可能是偶然的,但是!!如果加个循环收集那这个异常就成必然的了,如下:

走你:

如果将并行特性去掉呢?

居然木有报异常,好奇怪呀~~为啥加了并行特性与否其造成的结果还不一样呢?下次再来分析原因。

java8学习之自定义收集器深度剖析与并行流陷阱的更多相关文章

  1. java8学习之自定义收集器实现

    在上次花了几个篇幅对Collector收集器的javadoc进行了详细的解读,其涉及到的文章有: http://www.cnblogs.com/webor2006/p/8311074.html htt ...

  2. Java8学习笔记(十)--自定义收集器

    前言 以前写过Java8中的自定义收集器,当时只是在文章末尾放了个例子,觉得基本用法挺简单,而且有些东西没搞懂(比如combiner方法到底做什么的),没有专门写,过了一段时间又忘了,所以,即使还是没 ...

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

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

  4. Java8中重要的收集器Collector

    Collector介绍 Java8的stream api能很方便我们对数据进行统计分类等工作,函数式编程的风格让我们方便并且直观地编写统计代码. 例如: Stream<Integer> s ...

  5. Java虚拟机JVM学习06 自定义类加载器 父委托机制和命名空间的再讨论

    Java虚拟机JVM学习06 自定义类加载器 父委托机制和命名空间的再讨论 创建用户自定义的类加载器 要创建用户自定义的类加载器,只需要扩展java.lang.ClassLoader类,然后覆盖它的f ...

  6. java类加载器学习2——自定义类加载器和父类委托机制带来的问题

    一.自定义类加载器的一般步骤 Java的类加载器自从JDK1.2开始便引入了一条机制叫做父类委托机制.一个类需要被加载的时候,JVM先会调用他的父类加载器进行加载,父类调用父类的父类,一直到顶级类加载 ...

  7. Struts学习之自定义拦截器

    * 所有的拦截器都需要实现Interceptor接口或者继承Interceptor接口的扩展实现类    * 要重写init().intercept().destroy()方法        * in ...

  8. libevent学习笔记(参考libevent深度剖析)

    最近自学libevent事件驱动库,参考的资料为libevent2.2版本以及张亮提供的<Libevent源码深度剖析>, 参考资料: http://blog.csdn.net/spark ...

  9. Struts2重新学习之自定义拦截器(判断用户是否是登录状态)

    拦截器 一:1:概念:Interceptor拦截器类似于我们学习过的过滤器,是可以再action执行前后执行的代码.是web开发时,常用的技术.比如,权限控制,日志记录. 2:多个拦截器Interce ...

随机推荐

  1. [译]AngularJS 1.3.0 开发者指南(一) -- 介绍 (转)

    http://www.cnblogs.com/lzj0616/p/6440563.html [译]AngularJS 1.3.0 开发者指南(一) -- 介绍 Angular是什么 ? Angular ...

  2. java浮点型数据保留两位小数

    /*** * 保留2位小数 * @param floatValue * @return */ float scale(Float floatValue) { DecimalFormat format ...

  3. python安装二进制k8s 1.11.0 一个master、一个node 查看node节点是主机名---apiserver无法启动,后来改了脚本应该可以

    一.脚本说明: 本实验中master.node.etcd都是单体. 安装顺序为:先安装test1节点主要组件,然后开始安装test2节点,最后回头把test1节点加入集群中,这样做目的是理解以后扩容都 ...

  4. extentreports 测试报告引用extend.js/css失败

    测试工程引用extentreports 生成的测试报告,因为报告中的js和css网络不通,所以页面乱码 解决思路: 下载需要的js.css放到测试工程的static目录下 下载extentreport ...

  5. Oracle:常用操作(定时作业,逻辑导入,数据泵导入)

    1.逻辑导入: /*第1步:创建临时表空间 **/ create temporary tablespace user_temp1 tempfile 'D:\app\Administrator\orad ...

  6. 微信小程序动画:高度渐变,left渐变

    今天在测试微信小程序动画的时候遇到了坑,需求是这样的点击时子元素从外部滑动回来,父元素的高度跟随子元素的高度改变. 实现子元素left为0并不复杂,但是改变父元素box的高度的时候却遇到了坑,因为是需 ...

  7. 看我如何通过邮箱获取IP定位-复现

    环境准备:一台部署了phpstudy 的vps 脚本内容:get_ip.php 该脚本可以生成一个十分隐蔽的图片,并获取客户端的一些敏感信息. 代码内容如下: <?php //show_sour ...

  8. 【CSP模拟】小凯的疑惑(DP)

    首先,这道题正解的思路是从subtask2而得来的,所以先讲一下subtask2的做法. 因为保证答案不超过long long,所以直接求最大权独立集即可:dp[u][0]表示u点一定不能取的答案,d ...

  9. python smtplib server not connect

    最近发现用smtplib发邮件一直发送不成功,使用debug发现前面都正常,但是DATA发送直接被smtp服务器直接断开.smtp服务器显示body丢失. 后来发现是我加了附件,有指定文件类型: at ...

  10. [转帖]ASML发布Q1季度财报 营收22.3亿欧元,EUV光刻机下半年产能大增 ...

    ASML发布Q1季度财报营收22.3亿欧元,EUV光刻机下半年产能大增 ... 孟宪瑞发布于2019-4-18 10:32 https://www.expreview.com/67969.html 一 ...