Java 8 自定义流Collector实现

前文我们看到 Java 8 Collectors提供了很多内置实现。但有时我们需要实现一些特定功能满足业务需要,本文带你学习如何自定义Collector的实现,计算字符串流中所有单词的长度。

需求说明

假设有字符串流,利用每个字符串对象有方法length()————计算并返回单词长度。我们想创建自定义Collector,实现reduce操作,计算流中所有单词的长度之和。

使用 Collector.of() 方法

为了创建自定义Collector,需要实现Collector接口。现在,我们不使用传统方法,而是使用Collector.of()静态方法创建自定义Collector。

不仅是为了更精简和增强可读性,还因为这种方法可以忽略部分不必要的实现。实际上,Collector接口仅需要三个必须部分————提供者(supplier), 累加器(accumulator) 以及合并器(combiner)。

结果容器提供者(supplier)

实现Collector,必须提供结果容器,即累加值存储的地方。下面代码提供了结果容器:

() -> new int[1]

你可能会想,为什么是 new int[1],而不是int变量作为初始化值。原因是Collector接口需要结果容器能够以可变的方式进行更新。

累加元素(accumulator)

接下来,我们需要创建函数实现增加元素至结果容器。在我们的示例中,即单词的长度增加至结果容器:

(result, item) -> result[0] += item.length()

该函数是Consumer类型,其不返回任何值,仅以可变的方式更新结果容器————即数组中的第一个元素。

合并器(combiner)

在reduction序列操作中,提供者(supplier) 和 累加器(accumulator) 已经足够了,但为了能够实现并行操作,我们需要实现一个合并器。合并器(combiner)是定义两个结果如何合并的函数。
在并行环境下,流被分为多个部分,每个部分被并行累加。当所有部分都完成时,结果需要使用合并器函数进行合并。下面请看我们的实现代码:

(result1, result2) -> {result1[0] += result2[0];return result1;
}

最小的自定义Collector

现在我们已经所有必要组件,整合在一起就是我们的Collector:

 wordStream.collect(Collector.of(()-> new int[1],(result, item) -> result[0] += item.length(),(result1, result2) -> {result1[0] += result2[0];return result1;}
));

上面方案有个小问题,其直接返回结果容器即int[]类型。实际我们需要的字符串长度,不是结果容器。

最后一个转换

我们可以很容易实现,增加一个函数,其映射结果容器至我们需要的类型。这里我们仅仅需要数组的第一个元素:

total -> total[0]

最后完整代码为:

    private List<String> wordList = Arrays.asList("tommy", "is", "a", "java", "developer");@Testpublic void wordCountTest() {Stream<String> wordStream = wordList.stream();int wordCnt = wordStream.collect(Collector.of(()-> new int[1],(result, item) -> result[0] += item.length(),(result1, result2) -> {result1[0] += result2[0];return result1;},total -> total[0]));System.out.println("wordCnt = " + wordCnt);}

如果把我们自定义的Collector赋值给变量,则代码可以简化为:

int wordCount = wordStream.collect(totalWordCountCollector);

优化参数

最后,我们看下优化参数。即自定义Collector支持不同类型的优化参数。
使用Collector.of() 可以在参数最后增加 Characteristics 作为可变参数:

Collector.of(  // supplier,// accumulator,// combiner,// finisher, Collector.Characteristics.CONCURRENT,Collector.Characteristics.IDENTITY_FINISH,// ...
);

有三种 Characteristics 可以使用:

  • CONCURRENT — 指明结果容器可以被多个并发累加器使用
  • IDENTITY_FINISH — 指明结束函数是恒等函数且可以被忽略
  • UNORDERED — 指明collector不依赖元素顺序

总结

本文我们学习了如何自定义Java 8 自定义 流的 Collector实现.更多内容可以参考官方文档。

Java 8 自定义流Collector实现相关推荐

  1. 怎么在java中创建一个自定义的collector

    文章目录 简介 Collector介绍 自定义Collector 总结 怎么在java中创建一个自定义的collector 简介 在之前的java collectors文章里面,我们讲到了stream ...

  2. java全局变量怎么定义_怎么在java中创建一个自定义的collector

    简介 在之前的java collectors文章里面,我们讲到了stream的collect方法可以调用Collectors里面的toList()或者toMap()方法,将结果转换为特定的集合类. 今 ...

  3. c++中的new_怎么在java中创建一个自定义的collector

    简介 在之前的java collectors文章里面,我们讲到了stream的collect方法可以调用Collectors里面的toList()或者toMap()方法,将结果转换为特定的集合类. 今 ...

  4. java中collector使用_怎么在java中创建一个自定义的collector

    怎么在java中创建一个自定义的collector 简介 在之前的java collectors文章里面,我们讲到了stream的collect方法可以调用Collectors里面的toList()或 ...

  5. 【Java 8】流(Stream API)

    本文参考书籍<Java 8实战>,陆明刚.劳佳  译,如有侵权,请联系删除! 在本章中,我们会使用这样一个例子:一个menu,它是一张菜肴列表: List<Dish> menu ...

  6. Java基础—IO流

    第一讲   IO概述 1. 流的概念 IO流即InputOutput的缩写,在Java中IO流用来处理设备之间的数据传输,Java对数据的操作是通过IO流的方式, 我们可以把IO流抽象的当作一根管道, ...

  7. Java IO: 字符流的Buffered和Filter

    作者: Jakob Jenkov  译者: 李璟(jlee381344197@gmail.com) 本章节将简要介绍缓冲与过滤相关的reader和writer,主要涉及BufferedReader.B ...

  8. 三万字的java I/O流基础总结看完肯定能把女朋友教会

    目录: 1.File类详解 2.I/O流概述 3.字节输出流(OutputStream) 4.字节输入流(InputStream) 5. 字符流概述 6.字符输入流(Reader) 7.字符输出流(W ...

  9. Java 8 Stream 流用法及语法

    Java 8 Stream 流用法 1.简介 Stream流 最全的用法 Stream 能用来干什么?用来处理集合,通过 使用Stream API 对集合数据进行操作,就类似于使用 SQL 执行的数据 ...

最新文章

  1. 【神经网络】(8) 卷积神经网络(Mobilenet_v1),案例:cifar图像10分类
  2. 什么是静态UItableView
  3. Reverse Vowels of a String
  4. aes sample java,python-AES加密java解密
  5. Autolisp:利用AuoCAD之Lisp编程案例之自动智能获取所选对象的面积并标注在指定位置
  6. JZOJ 5396. 【NOIP2017提高A组模拟10.6】Blocks
  7. PHP 安装xdebug
  8. mysql 导出数据字典_操作MySQL?这个库比pymysql香一百倍
  9. 你还在使用xml配置mybatis吗,快来试试这种方式吧
  10. coolfire文章之七
  11. 谷歌关闭中国音乐搜索服务--有点可惜
  12. Linux 命令(184)—— at 命令
  13. php 个人摄影,展示个人摄影作品的12种方式(ZT)
  14. 梯度下降——雏凤清于老凤声
  15. mac mysql 自动启动_Mac设置Mysql开机启动
  16. js的数据类型和强制类型转换
  17. 2018 中国大陆网速排名世界 141 位;Linux 4.18 内核发布
  18. 暴风播酷云二期J3455 DS918 1.04b引导6.23完美群晖教程,可硬洗,正常开关机、WOL
  19. Python math.degrees() 方法
  20. duo是什么意思_为什么说陈奕迅的《浮夸》可能是一首细思极恐的粤语歌?

热门文章

  1. opencv根据颜色抠图
  2. java工厂模式的优势,java 工厂模式的讲解及优缺点的介绍
  3. java从弃坑到web
  4. A*寻路 -- 更加真实 的路径(一)
  5. 翌加科技:抖音商品侵权如何处理
  6. arduino圆孔供电_Arduino Uno的多种供电方式 电源选择电路的原理
  7. Word中打不出来的符号公式
  8. ORBSLAM2学习笔记2(KeyFrame)
  9. 荣耀系列手机耗电优化图解
  10. 数值积分的龙贝格(Romberg)算法和梯形变步长算法的对比