自定义收集器深度剖析:

在上次【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. 系统启动热键(Boot Hotkey)

    1.HP ENVY 13 F1 --> 系统信息F2 --> 系统检测F9 --> 启动设备选项F10 --> 设置BIOSF11 --> 系统恢复ENTER --> ...

  2. windows修复失效图标

    taskkill /im explorer.exe /fcd /d %userprofile%\appdata\localdel iconcache.db /astart explorer.exeex ...

  3. Golang中基础的命令行模块urfave/cli

    前言相信只要部署过线上服务,都知道启动参数一定是必不可少的,当你在不同的网络.硬件.软件环境下去启动一个服务的时候,总会有一些启动参数是不确定的,这时候就需要通过命令行模块去解析这些参数,urfave ...

  4. configparser模块,subprocess 模块,xlrd,xlwt ,xml 模块,面向对象

    1. configparser模块 2.subprocess 模块 3.xlrd,xlwt 4.xml 模块 5.面向对象 面向对象是什么? 是一种编程思想,指导你如何更好的编写代码 关注点在对象 具 ...

  5. 应用安全 - 工具|平台 - Elasticsearch- 漏洞 - 汇总

    未授权访问 (1)/_cat/indices #Index个数查询 (2)/_mapping?pretty=true #type个数查询 (3)根据Index和type查询表数据 (4)/_river ...

  6. WinForm笔记1:TextBox编辑时和DataGridView 单元格编辑时 的事件及其顺序

    TextBox 编辑框 When you change the focus by using the mouse or by calling the Focus method, focus event ...

  7. 引用Nuget包Microsoft.EntityFrameworkCore.Tools.DotNet报错

    错误如下 解决方法 使用VS2017或更高版本在改项目右键,选择“编辑xxx.csproj”,并添加如下一句话,就可以成功引用改Nuget包 <PackageReference Include= ...

  8. python 学习jieba库遇到的问题及解决方法

    昨天在课堂上学习了jieba库,跟着老师写了同样的代码时却遇到了问题: jieba分词报错AttributeError: module 'jieba' has no attribute 'cut' 文 ...

  9. elasticsearch教程--中文分词器作用和使用

    概述   本文都是基于elasticsearch安装教程 中的elasticsearch安装目录(/opt/environment/elasticsearch-6.4.0)为范例 环境准备 ·全新最小 ...

  10. Python学习【day02】- Python基础练习题

    #!/usr/bin/env python # -*- coding:utf8 -*- # 执行Python 脚本的两种方式 # 答:①在windows的cmd窗口下 > D:/Python/p ...