package com.lgx.jdk8.part02;

import java.util.*;

import java.util.function.BiConsumer;

import java.util.function.BinaryOperator;

import java.util.function.Function;

import java.util.function.Supplier;

import java.util.stream.Collector;

/**

* 自定义Collector,定义一个Set收集器

*/

public class Test13MySetCollector{

public static void main(String[] args) {

List list = Arrays.asList("hello", "world", "hello", "welcome");

Set set = list.stream().collect(new MySetCollector<>());

System.out.println("set = " + set);

System.out.println("========================");

List list2 = Arrays.asList("hello", "world", "hello", "welcome", "a", "b", "c", "d");

Set set2 = new HashSet<>();

set2.addAll(list2);

System.out.println("set2 = " + set2);

//如果parallel和sequential写多个,以最后一个为准,因为在实现中就是以一个boolean来判断的

for (int i = 0; i < 1; i++) {//执行100次验证并行,加这个参数CONCURRENT报错问题

//Map map = set2.stream().collect(new MyMapCollector<>()); //串行

//Map map = set2.parallelStream().collect(new MyMapCollector<>()); //并行

Map map = set2.stream().sequential().collect(new MyMapCollector<>()); //串行

//Map map = set2.stream().parallel().collect(new MyMapCollector<>()); //并行

System.out.println("map = " + map);

}

System.out.println("可运行线程数=总cpu-被占用的cpu = " + Runtime.getRuntime().availableProcessors());

}

}

//自定义收集器,输入时Set,输出是Set

class MySetCollector implements Collector, Set> {

//创建一个新的容器

@Override

public Supplier> supplier() {

System.out.println("MySetCollector supplier invoked");

return HashSet::new;

}

//累加器:添加一个元素到容器

@Override

public BiConsumer, T> accumulator() {

System.out.println("MySetCollector accumulator invoked");

//return HashSet::add;//这里不能给一个具体的Set,因为supplier方法可能返回的是TreeSet,不一定是HashSet

return Set::add;

}

//把并行流多个结果合并

@Override

public BinaryOperator> combiner() {

System.out.println("MySetCollector combiner invoked");

return (set1, set2) -> {

set1.addAll(set2);

return set1;

};

}

//完成器:合并完返回最终结果

@Override

public Function, Set> finisher() {

System.out.println("MySetCollector finisher invoked");

//return t -> t;

return Function.identity();//与上面那个等价

//throw new UnsupportedOperationException();

}

//返回一个集合,标识这个集合的诸多特性

/**

* Characteristics有3个值:

* CONCURRENT:表示可以并行收集

* UNORDERED:元素不保证顺序的

* IDENTITY_FINISH:表示会执行一个强制类型转换,会调用finisher()方法

*/

@Override

public Set characteristics() {

System.out.println("MySetCollector characteristics invoked");

return Collections.unmodifiableSet(EnumSet.of(Characteristics.IDENTITY_FINISH, Characteristics.UNORDERED));

}

}

//自定义收集器,输入时Set,输出是Map

class MyMapCollector implements Collector, Map> {

//创建一个新的容器

@Override

public Supplier> supplier() {

System.out.println("MyMapCollector supplier invoked");

//return HashSet::new;

return () -> {

System.out.println("***************");//串行这里只执行一次,并行这里执行多次

return new HashSet();

};

}

//累加器:添加一个元素到容器

@Override

public BiConsumer, T> accumulator() {

System.out.println("MyMapCollector accumulator invoked");

//return Set::add;

return (set, item) -> {

System.out.println("MyMapCollector accumulator set = " + set + " " + Thread.currentThread().getName());

//报错在于这里调用(打印)了set,和下面的代码产生了一边修改一边迭代,删掉这个打印就好了

set.add(item);

};

}

//把并行流多个结果合并

@Override

public BinaryOperator> combiner() {

System.out.println("MyMapCollector combiner invoked");

return (set1, set2) -> {

set1.addAll(set2);

System.out.println("MyMapCollector combiner set1 = " + set1 + " set2 = " + set2);

return set1;

};

}

//完成器:合并完返回最终结果

@Override

public Function, Map> finisher() {

System.out.println("MyMapCollector finisher invoked");

return set -> {

Map map = new HashMap();

set.stream().forEach(item -> map.put(item, item));

return map;

};

}

//返回一个集合,标识这个集合的诸多特性

@Override

public Set characteristics() {

System.out.println("MyMapCollector characteristics invoked");

//return Collections.unmodifiableSet(EnumSet.of(Characteristics.IDENTITY_FINISH));//运行会报错,因为这样会执行强制类型转换,而事实上无法将一个Set强制转换成Map

/**

* Characteristics.CONCURRENT:

* 如果上面调用parallelStream,不管有没有这个属性都是并行

* 不加这个属性,是多个线程操作多个结果容器,combiner也会调用多次

* 加了这个属性,是多个线程操作一个结果容器,combiner也无需调用了

*/

return Collections.unmodifiableSet(EnumSet.of(Characteristics.UNORDERED));//合并方法执行多次

//return Collections.unmodifiableSet(EnumSet.of(Characteristics.UNORDERED, Characteristics.CONCURRENT));//合并方法不会执行,多次运行该示例可能抛出异常ConcurrentModificationException

/**

* ConcurrentModificationException:并发修改异常,一个线程修改在一个集合,另一个集合在迭代这个集合,就会报出这个异常

* 不加CONCURRENT,多个容器,也就互不干扰了;加了就一个容器,就会出现这个问题

*/

}

}

java 自定义 operator_java8 自定义Collector相关推荐

  1. java 8流自定义收集器_Java 8编写自定义收集器简介

    java 8流自定义收集器 Java 8引入了收集器的概念. 大多数时候,我们几乎不使用Collectors类中的工厂方法,例如collect(toList()) , toSet()或其他更有趣的方法 ...

  2. 【Java 注解】自定义注解 ( 使用注解实现简单测试框架 )

    文章目录 一.定义注解 二.使用注解 三.解析注解 在 [Java 注解]自定义注解 ( 注解属性定义与赋值 ) 博客中讲解了 注解属性 ; 在 [Java 注解]自定义注解 ( 元注解 ) 博客中讲 ...

  3. 【Java 注解】自定义注解 ( 注解解析 )

    文章目录 一.定义注解 二.使用注解 三.解析注解 四.通过注解对象获取注解属性的原理 在 [Java 注解]自定义注解 ( 注解属性定义与赋值 ) 博客中讲解了 注解属性 ; 在 [Java 注解] ...

  4. centos 开机启动java_Centos 7将java jar包自定义开机启动服务

    Centos 7将java jar包自定义开机启动服务 1. 先上 jar包的启动脚本 vim service.sh #!/bin/bash # 需要变更的参数 # 先查看java绝对路径:which ...

  5. java闪屏怎么制作,Java Swing创建自定义闪屏:在闪屏下画进度条(一)

    Java Swing创建自定义闪屏:在闪屏上画进度条(一) 由于本人十分热爱Java Swing,所以平时闲暇之余总是喜欢极尽所能去搜藏一些自认为比较"酷"的Swing代码来研究揣 ...

  6. Java针对ArrayList自定义排序的2种实现方法

    这篇文章主要介绍了Java针对ArrayList自定义排序的2种实现方法,结合实例形式总结分析了Java操作ArrayList自定义排序的原理与相关实现技巧,下面就和动力节点java学院小编一起来看看 ...

  7. java android长连接_基于Java Socket的自定义协议,实现Android与服务器的长连接(一)...

    一.基础知识准备 在正式给大家介绍自定义协议之前,我们先对网络传输和协议解析的相关知识点做一个基本的介绍,尽管这些知识点我们在学校里学过,但难免会有所遗忘,这里先做一个简单的介绍,以便对后文的内容理解 ...

  8. java调用kettle自定义kettle.properties配置文件路径

    java调用kettle自定义kettle.properties配置文件路径 默认路径 java调用kettle的jar包时,在初始化环境的时候,会在指定路径创建并加载kettle的kettle.pr ...

  9. java反射实现自定义json转对象方法-忽略字段大小写、字段个数

    java反射实现自定义json转对象方法-忽略字段大小写.字段个数 开发过程中经常会遇到json转对象,可以使用FastJson或者Gson自带的工具类进行转换,但当遇到json与对象属性名称大小写不 ...

最新文章

  1. usermod命令的一些用法详解
  2. WCF单元测试遇到的问题
  3. LIS(基于贪心的O(NlogN)解法)
  4. 应届生拿到offer之后的流程_【经验】我是如何一步步拿到拼多多amp;京东amp;艺龙等多个产品offer的...
  5. angularjs1.x版本,父子组件之间的双向绑定
  6. 销售易CRM:提高管理效率需做好业绩预测
  7. html弹出框交互,HTML5/SVG模态窗口(对话框)交互动画
  8. 品牌类软文经典案例分享,深刻了解软文营销的“魅力”
  9. VOSviewer软件研究热点分析
  10. Python -- 扫描局域网活跃IP
  11. HTML布局方式Flex属性详解
  12. 初始vue脚手架的项目文件中mian.js文件
  13. ADS1256,引起了通信丢失
  14. 聊聊电商系统中红包活动设计
  15. 服务器内置usb能否修改为外置,台式机内置的DVD刻录机可以改成外置的USB接口吗?...
  16. layer的anim动画
  17. CMMI有哪几个级别,每个级别有哪些其特征
  18. windows SDK模拟游戏钢琴的实现(一)
  19. 【牛客网面经整理】20200831小米一面
  20. opencv计算机视觉_opencv是计算机视觉的至尊工具

热门文章

  1. mongodb数据库扩展名_MongoDB学习笔记:MongoDB 数据库的命名、设计规范
  2. Windows最经典应用大变脸:学生爽翻!
  3. OpenWrt启动过程分析+添加自启动脚本【转】
  4. 从尼古拉斯·泽卡斯开始学习
  5. java并发的艺术-读书笔记-第八章常用的并发工具类
  6. Oracle获取最近执行的SQL语句
  7. robots.txt网站爬虫文件设置
  8. 用jquery mobile 实现幻灯片效果
  9. DrawerLayout + Toolbar + ViewPager
  10. $emit传递多个参数_Go语言参数传递方式