自定义收集器深度剖析:

在上次【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. OpenID简介

    OpenID 是一个以用户为中心的数字身份识别框架,它具有开放.分散性.OpenID 的创建基于这样一个概念:我们可以通过 URI (又叫 URL 或网站地址)来认证一个网站的唯一身份,同理,我们也可 ...

  2. [笔记] 使用v2r访问外网

    介绍 首先,你需要有一台能上外网的服务器,如AWS,GCP等. 其次,请自行复制全文,然后将FXXK替换为v2r的全称(5个小写字符). 服务器上Docker镜像配置流程 拉取镜像 $ sudo do ...

  3. minio 集群启动方法

    Sample: export MINIO_ACCESS_KEY=<TENANT1_ACCESS_KEY> export MINIO_SECRET_KEY=<TENANT1_SECRE ...

  4. JavaScript基础入门06

    目录 JavaScript 基础入门06 Math 对象 Math对象的静态属性 Math对象的静态方法 指定范围的随机数 返回随机字符 三角函数 Date对象 基础知识 日期对象具体API 构造函数 ...

  5. Object.assign()的用法 -- 用于将所有可枚举属性的值从一个或多个源对象复制到目标对象,返回目标对象

    语法: Object.assign(target, …sources) target: 目标对象,sources: 源对象用于将所有可枚举属性的值从一个或多个源对象复制到目标对象.它将返回目标对象. ...

  6. PJzhang:微软出口管制条例

    猫宁!!! 翻译:PJzhang 微软公司的技术,产品和服务受美国出口管理法规(EAR)的约束,由美国商务部工业与安全局(BIS)监督执行. 此外,财政部,国务院对其他与出口相关的技术和产品转让,交易 ...

  7. 如何为Redis中list中的项设置过期时间

    问题 两种解决方法 有序集合 多个集合以及TTL Redis是一个伟大的工具,用来在内存中存储列表是很合适的. 不过,如果你想要快速搜索列表,同时需要让列表中每项都在一定时间后过期,应该怎么做呢? 首 ...

  8. 使用PowerShell 自动安装.NET4.6.1离线包

    自动安装脚本在文章末尾 自动安装脚本在文章末尾 自动安装脚本在文章末尾 运行环境:Windows Server 2012 R2 开发环境:Win10 Microsoft .NET Framework ...

  9. K8s开始

    部署前思考:

  10. Hanlp配置自定义词典遇到的问题与解决方法

    本文是整理了部分网友在配置hanlp自定义词典时遇到的一小部分问题,同时针对这些问题,也提供另一些解决的方案以及思路.这里分享给大家学习参考. 要使用hanlp加载自定义词典可以通过修改配置文件han ...