自定义收集器深度剖析:

在上次【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. 【转】Spark History Server 架构原理介绍

    [From]https://blog.csdn.net/u013332124/article/details/88350345 Spark History Server 是spark内置的一个http ...

  2. Opencv-python3.3版本安装

    因为目前为止(2019.11.17)opencv最新版本为4.1,因此直接pip install opencv-python的话,无法安装想要的版本(老师推荐3.X) 上清华镜像查找opencv-py ...

  3. nginx 反向代理是url带后缀

    1.后端:http://10.253.149.2/tdsqlpcloud/index.php 2.配置文件 danjan01deiMac:nginx danjan01$ cat /usr/local/ ...

  4. mysql——操作数据库

    一.查看数据库 show databases; 二.创建数据库 create database 数据库名; 三.删除数据库 drop database 数据库名; 四.查看数据库存储引擎 show e ...

  5. [爬虫] selenium介绍

    认识selenium 在爬取百度文库的过程中,我们需要使用到一个工具selenium(浏览器自动测试框架),selenium是一个用于web应用程序测试的工具,它可以测试直接运行在浏览器中,就像我们平 ...

  6. [转帖] Linux下面计算文件数量的方法

    Linux命令-查看目录下文件个数 2018年07月04日 10:37:07 sand_clock 阅读数 2002    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blo ...

  7. python中argparse模块简单使用

    python中argparse模块简单使用 简介 argparse是python用于解析命令行参数和选项的标准模块.argparse模块的作用是用于解析命令行参数. 使用步骤 1.首先导入该模块 2. ...

  8. 使用Visual Studio 2019--调试汇编32位代码的详细步骤

    声明:本文使用32位masm,代码与16位,64位不同 ------------------------------------------------------------------------ ...

  9. vue : 无法加载文件 C:\Users\lihongjie\AppData\Roaming\npm\vue.ps1,因为在此系统上禁止运行脚本。有关详细信息,请参阅 htt ps:/go.microsoft.com/fwlink/?LinkID=135170 中的 about_Execution_Policies。 所在位置 行:1 字符: 1 + vue init webpack vue_p

    以管理员方式打开powershell 运行命令:set-ExecutionPolicy RemoteSigned 出现: 执行策略更改执行策略可帮助你防止执行不信任的脚本.更改执行策略可能会产生安全风 ...

  10. 纯H5 AJAX文件上传加进度条功能

    上传代码js部分 //包上传 $('.up_apk').change(function () { var obj = $(this); var form_data = new FormData(); ...