怎么在java中创建一个自定义的collector
怎么在java中创建一个自定义的collector
简介
在之前的java collectors文章里面,我们讲到了stream的collect方法可以调用Collectors里面的toList()或者toMap()方法,将结果转换为特定的集合类。
今天我们介绍一下怎么自定义一个Collector。
Collector介绍
我们先看一下Collector的定义:

Collector接口需要实现supplier(),accumulator(),combiner(),finisher(),characteristics()这5个接口。
同时Collector也提供了两个静态of方法来方便我们创建一个Collector实例。
我们可以看到两个方法的参数跟Collector接口需要实现的接口是一一对应的。
下面分别解释一下这几个参数:
- supplier
Supplier是一个函数,用来创建一个新的可变的集合。换句话说Supplier用来创建一个初始的集合。accumulator
- accumulator
accumulator定义了累加器,用来将原始添加到集合中。
- combiner
combiner用来将两个集合合并成一个。
- finisher
finisher将集合转换为最终的集合类型。
- characteristics
characteristics表示该集合的特征。这个不是必须的参数。
有了这几个参数,我们接下来看看怎么使用这些参数来构造一个自定义Collector。
自定义Collector
我们利用Collector的of方法来创建一个不变的Set:
public static <T> Collector<T, Set<T>, Set<T>> toImmutableSet() {
return Collector.of(HashSet::new, Set::add,
(left, right) -> {
left.addAll(right);
return left;
}, Collections::unmodifiableSet);
}
上面的例子中,我们HashSet::new作为supplier,Set::add作为accumulator,自定义了一个方法作为combiner,最后使用Collections::unmodifiableSet将集合转换成不可变集合。
上面我们固定使用HashSet::new作为初始集合的生成方法,实际上,上面的方法可以更加通用:
public static <T, A extends Set<T>> Collector<T, A, Set<T>> toImmutableSet(
Supplier<A> supplier) {
return Collector.of(
supplier,
Set::add, (left, right) -> {
left.addAll(right);
return left;
}, Collections::unmodifiableSet);
}
上面的方法,我们将supplier提出来作为一个参数,由外部来定义。
看下上面两个方法的测试:
@Test
public void toImmutableSetUsage(){
Set<String> stringSet1=Stream.of("a","b","c","d")
.collect(ImmutableSetCollector.toImmutableSet());
log.info("{}",stringSet1);
Set<String> stringSet2=Stream.of("a","b","c","d")
.collect(ImmutableSetCollector.toImmutableSet(LinkedHashSet::new));
log.info("{}",stringSet2);
}
输出:
INFO com.flydean.ImmutableSetCollector - [a, b, c, d]
INFO com.flydean.ImmutableSetCollector - [a, b, c, d]
总结
本文介绍了Collector和自定义Collector的实例,希望能对大家有所帮助。
本文的例子https://github.com/ddean2009/learn-java-streams/tree/master/customCollector
欢迎关注我的公众号:程序那些事,更多精彩等着您!
更多内容请访问 www.flydean.com
怎么在java中创建一个自定义的collector的更多相关文章
- springmvc在处理请求过程中出现异常信息交由异常处理器进行处理,自定义异常处理器可以实现一个系统的异常处理逻辑。为了区别不同的异常通常根据异常类型自定义异常类,这里我们创建一个自定义系统异常,如果controller、service、dao抛出此类异常说明是系统预期处理的异常信息。
springmvc在处理请求过程中出现异常信息交由异常处理器进行处理,自定义异常处理器可以实现一个系统的异常处理逻辑. 1.1 异常处理思路 系统中异常包括两类:预期异常和运行时异常RuntimeEx ...
- 在存放源程序的文件夹中建立一个子文件夹 myPackage。例如,在“D:\java”文件夹之中创建一个与包同名的子文件夹 myPackage(D:\java\myPackage)。在 myPackage 包中创建一个YMD类,该类具有计算今年的年份、可以输出一个带有年月日的字符串的功能。设计程序SY31.java,给定某人姓名和出生日期,计算该人年龄,并输出该人姓名、年龄、出生日期。程序使用YM
题目补充: 在存放源程序的文件夹中建立一个子文件夹 myPackage.例如,在“D:\java”文件夹之中创建一个与包同名的子文件夹 myPackage(D:\java\myPackage).在 m ...
- Java中创建线程的三种方式以及区别
在java中如果要创建线程的话,一般有3种方法: 继承Thread类: 实现Runnable接口: 使用Callable和Future创建线程. 1. 继承Thread类 继承Thread类的话,必须 ...
- java中创建线程的方式
创建线程的方式: 继承thread 实现runnable 线程池 FurureTask/Callable 第一种:继承thread demo1: public class demo1 { public ...
- JAVA中创建线程池的五种方法及比较
之前写过JAVA中创建线程的三种方法及比较.这次来说说线程池. JAVA中创建线程池主要有两类方法,一类是通过Executors工厂类提供的方法,该类提供了4种不同的线程池可供使用.另一类是通过Thr ...
- Java中创建操作文件和文件夹的工具类
Java中创建操作文件和文件夹的工具类 FileUtils.java import java.io.BufferedInputStream; import java.io.BufferedOutput ...
- 如何创建一个自定义jQuery插件
简介 jQuery 库是专为加快 JavaScript 开发速度而设计的.通过简化编写 JavaScript 的方式,减少代码量.使用 jQuery 库时,您可能会发现您经常为一些常用函数重写相同的代 ...
- JAVA中创建线程的三种方法及比较
JAVA中创建线程的方式有三种,各有优缺点,具体如下: 一.继承Thread类来创建线程 1.创建一个任务类,继承Thread线程类,因为Thread类已经实现了Runnable接口,然后重写run( ...
- Eclipse中创建一个新的SpringBoot项目
在Eclipse中创建一个新的spring Boot项目: 1. 首先在Eclipse中安装STS插件:在Eclipse主窗口中点击 Help -> Eclipse Marketplace... ...
随机推荐
- web存储cookie会出现两个相同键值问题
我使用js存储cookie,定义key值是menu,存储过程中出现了相同的menu键值而且有的时候有一个还是null,折腾了三四个小时不知道啥问题: 早上到公司后想着换换键值,就把键值换成了selec ...
- 8.MSFvenom
Meterpreter 01 Meterpreter API调用 Meterpreter提供了多种APl调用,在编写自己的脚本时可以使用这些API来提供额外功能或定制功能. 关于ruby的更多信息,请 ...
- Q - Queue HDU - 5493(树状树组维护区间前缀和 + 二分找预留空位)
Q - Queue HDU - 5493 Problem Description NNN people numbered from 1 to NNN are waiting in a bank for ...
- Oracle创建函数例子
编写一个函数计算学生某一门课程在班级内的排名. 表结构如下: create or replace function fun_score_rank( p_in_stuid in number,--学号 ...
- STM32F103ZET6的中断管理
1.STM32的中断 STM32的中断管理是属于内核部分的,所以中断管理的寄存器也是属于内核组,不属于芯片外设,在查看相关资料的时候,需要查看相对应的内核手册. STM32F103ZET6是Corte ...
- 数据库服务软件类型和配置redis
ql-day11 数据库服务软件类型和配置redis l 数据库服务软件类型 ² R ...
- var、let和const的区别详解
let 和 const 是 ECMAScript6 新推出的特性,其中 let 是能够替代 var 的"标准",所以我们探讨 var.let 和 const 的区别,首先应该知 ...
- 了解一下mock
1.mock简介: mock测试就是在测试过程中,对于某些不容易构成或者不容易获取的对象,用一个虚拟的对象来创建以便测试的测试方法,mock是在测试过程中,对于一些不容易构造/获取的对象,创建一个mo ...
- 手动搭建I/O网络通信框架4:AIO编程模型,聊天室终极改造
第一章:手动搭建I/O网络通信框架1:Socket和ServerSocket入门实战,实现单聊 第二章:手动搭建I/O网络通信框架2:BIO编程模型实现群聊 第三章:手动搭建I/O网络通信框架3:NI ...
- leetcode c++做题思路和题解(2)——链表的例题和总结
链表的例题和总结 0. 目录 环形链表 1. 环形链表 题目: https://leetcode-cn.com/problems/linked-list-cycle/ 看了别人的思路真是感概万千,思路 ...