怎么在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的更多相关文章

  1. springmvc在处理请求过程中出现异常信息交由异常处理器进行处理,自定义异常处理器可以实现一个系统的异常处理逻辑。为了区别不同的异常通常根据异常类型自定义异常类,这里我们创建一个自定义系统异常,如果controller、service、dao抛出此类异常说明是系统预期处理的异常信息。

    springmvc在处理请求过程中出现异常信息交由异常处理器进行处理,自定义异常处理器可以实现一个系统的异常处理逻辑. 1.1 异常处理思路 系统中异常包括两类:预期异常和运行时异常RuntimeEx ...

  2. 在存放源程序的文件夹中建立一个子文件夹 myPackage。例如,在“D:\java”文件夹之中创建一个与包同名的子文件夹 myPackage(D:\java\myPackage)。在 myPackage 包中创建一个YMD类,该类具有计算今年的年份、可以输出一个带有年月日的字符串的功能。设计程序SY31.java,给定某人姓名和出生日期,计算该人年龄,并输出该人姓名、年龄、出生日期。程序使用YM

    题目补充: 在存放源程序的文件夹中建立一个子文件夹 myPackage.例如,在“D:\java”文件夹之中创建一个与包同名的子文件夹 myPackage(D:\java\myPackage).在 m ...

  3. Java中创建线程的三种方式以及区别

    在java中如果要创建线程的话,一般有3种方法: 继承Thread类: 实现Runnable接口: 使用Callable和Future创建线程. 1. 继承Thread类 继承Thread类的话,必须 ...

  4. java中创建线程的方式

    创建线程的方式: 继承thread 实现runnable 线程池 FurureTask/Callable 第一种:继承thread demo1: public class demo1 { public ...

  5. JAVA中创建线程池的五种方法及比较

    之前写过JAVA中创建线程的三种方法及比较.这次来说说线程池. JAVA中创建线程池主要有两类方法,一类是通过Executors工厂类提供的方法,该类提供了4种不同的线程池可供使用.另一类是通过Thr ...

  6. Java中创建操作文件和文件夹的工具类

    Java中创建操作文件和文件夹的工具类 FileUtils.java import java.io.BufferedInputStream; import java.io.BufferedOutput ...

  7. 如何创建一个自定义jQuery插件

    简介 jQuery 库是专为加快 JavaScript 开发速度而设计的.通过简化编写 JavaScript 的方式,减少代码量.使用 jQuery 库时,您可能会发现您经常为一些常用函数重写相同的代 ...

  8. JAVA中创建线程的三种方法及比较

    JAVA中创建线程的方式有三种,各有优缺点,具体如下: 一.继承Thread类来创建线程 1.创建一个任务类,继承Thread线程类,因为Thread类已经实现了Runnable接口,然后重写run( ...

  9. Eclipse中创建一个新的SpringBoot项目

    在Eclipse中创建一个新的spring Boot项目: 1. 首先在Eclipse中安装STS插件:在Eclipse主窗口中点击 Help -> Eclipse Marketplace... ...

随机推荐

  1. Kafka监控:主要性能指标

    Kafka是什么? Kafka是一个分布式,有分区的,有副本的日志服务系统,由LinkedIn公司开发,并于2011年开源.从本质上来说,Kafka拥有一套可扩展的发布/订阅消息队列架构,并组成了一套 ...

  2. 测试Activity和Fragment的生命周期

    Activity的生命周期有7个函数,Fragment的生命周期有11个函数. Activity生命周期除上述6个方法还有一个Restart()方法,该方法在该Activity从不可见(仍存在)到重新 ...

  3. pyhton 信号量Semaphore和BoundedSemaphore

    Semaphore和BoundedSemaphore两个,用起来好像没啥区别 都是定义信号量 sem=threading.BoundedSemaphore(5) sem=threading.Semap ...

  4. 在vue项目中封装echarts的正确姿势

    为什么需要封装echarts 每个开发者在制作图表时都需要从头到尾书写一遍完整的option配置,十分冗余 在同一个项目中,各类图表设计十分相似,甚至是相同,没必要一直做重复工作 可能有一些开发者忘记 ...

  5. 计算机人推荐书目&网站(不断更新)

    计算机人推荐书目&网站(不断更新) 鉴于最近有很多同学问我学什么读什么书好,我把我自己的经历和愚见写下来,仅供参考.我只会写我亲自读过有感悟的书,而不会搬运一些我碰都没有碰过只闻大名的书.本人 ...

  6. 版本控制,svn基础,实战案例,RPM打包

                                                   版本控制,svn基础,实战案例,RPM打包 案例1:Subversion基本操作 案例2:使用Subver ...

  7. JVM 理解性学习(一)

    重新学习,重新理解 1.类加载过程等 验证:.class 文件加载到 JVM 里的时候,会验证下该文件是否符合 JVM 规范. 准备:给实体类分配内存空间,以及给类变量(static 修饰)分配&qu ...

  8. Scrapy-01-追踪爬取

    目的:利用scrapy完成盗墓笔记小说的抓取 创建项目: scrapy   startproject    books cd  books scrapy   genspider    dmbj 编写p ...

  9. go 基本包

    像 fmt.os 等这样具有常用功能的内置包在 Go 语言中有 150 个以上,它们被称为标准库,大部分(一些底层的除外)内置于 Go 本身 unsafe: 包含了一些打破 Go 语言“类型安全”的命 ...

  10. 2017蓝桥杯贪吃蛇(C++C组)

    原题: 贪吃蛇长度+-------------------------------------------------+|                                        ...