热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

[四]java8函数式编程收集器浅析收集器Collector常用方法运行原理内部实现

Collector常见用法常用形式为:.collect(Collectors.toList())collect()是Stream的方法Collectors是收集器Collector

Collector常见用法

 

 


常用形式为:   .collect(Collectors.toList())

collect()是Stream的方法

Collectors  是收集器Collector 的工厂方法,提供了一些常用的收集器 

比如

image_5b7bb60d_263d

image_5b7bb60d_7cfe


 


常用收集器概要


收集器行为
toList()将元素收集到一个  List 中。
toSet()将元素收集到一个  Set 中。
toCollection()将元素收集到一个  Collection 中。
toMap(...)将元素收集到一个  Map 中,依据提供的映射函数将元素转换为键/值。
summingInt(ToIntFunction)给定值序列进行求和(还有  long 和  double 版本)
summarizingInt(ToIntFunction)给定值序列计算统计信息 sum min max count 和  average   (还有  long 和  double 版本)
reducing(...)用于归约计算(通常用作下游收集器,比如用于  groupingBy 或者partitioningBy 下游)
partitioningBy(...)按照predicate分为两组
groupingBy(...)将元素分组
maxBy(Comparator comparator)最大值
minBy(Comparator comparator)最小值
mapping(Function, Collector)将提供的映射函数应用于每个元素,并使用指定的下游收集器(通常用作下游收集器本身,比如用于  groupingBy)进行处理。
joining()假设元素为  String 类型,将这些元素联结到一个字符串中(或许使用分隔符、前缀和后缀)。
counting()计算元素数量。(通常用作下游收集器。)
averagingInt(ToIntFunction)平均数     (还有  long 和  double 版本)

 


收集器参数列表


toList()

toSet()

toCollection(Supplier)

counting()

collectingAndThen(Collector, Function)

summingInt(ToIntFunction)

summingLong(ToLongFunction)

summingDouble(ToDoubleFunction)

maxBy(Comparator)

minBy(Comparator)

reducing(BinaryOperator)

reducing(T, BinaryOperator)

reducing(U, Function, BinaryOperator)

joining()

joining(CharSequence)

joining(CharSequence, CharSequence, CharSequence)

mapping(Function, Collector)

toMap(Function, Function)

toMap(Function, Function, BinaryOperator)

toMap(Function, Function, BinaryOperator, Supplier)

toConcurrentMap(Function, Function)

toConcurrentMap(Function, Function, BinaryOperator)

toConcurrentMap(Function, Function, BinaryOperator, Supplier)

groupingBy(Function)

groupingBy(Function, Supplier, Collector)

groupingBy(Function, Collector)

groupingByConcurrent(Function)

groupingByConcurrent(Function, Supplier, Collector)

groupingByConcurrent(Function, Collector)

partitioningBy(Predicate)

partitioningBy(Predicate, Collector)

averagingDouble(ToDoubleFunction)

averagingInt(ToIntFunction)

averagingLong(ToLongFunction)

summarizingDouble(ToDoubleFunction)

summarizingInt(ToIntFunction)

summarizingLong(ToLongFunction)

 



 


收集器详解

 

Collector

image_5b7bb60d_7a4f


T - 输入类型

A - 在收集过程中用于累积部分结果的对象类型

R - 返回类型


 

 


mutable reduction的一些场景:

将元素聚集到集合中

使用StringBuilder连接字符串

计算有关元素的汇总信息,如sum、min、max或平均值

计算“主表”摘要,如“卖方的最大价值交易”等

类Collectors提供了许多常见的reduce实现

 

收集器构成

收集器是由四个函数约定构成,它们一起工作,将条目汇集到一个可变的结果容器中,并可选择性地对结果执行最终转换。

 


1. 创建一个新的结果容器(supplier())

2.  将一个新的数据元素合并到一个结果容器中(accumulator())

3. 将两个结果容器合并成一个(combiner())             

     (非必然运行  可能在并行流且Collector不具备CONCURRENT   时执行的  )

4. 在容器上执行一个可选的最终转换 (finisher())     

     (非必然运行  中间结果与最终结果类型是否一致决定是否运行 IDENTITY_FINISH用来标志  )  

 

 

属性特征字段

 


特征值是Collector的特征值,用于描述Collecto本身r的,不是其他含义
 Set characteristics()  方法可以访问

Collector.Characteristics  CONCURRENT 

表示中间结果只有一个,即使在并行流的情况下

所以只有在并行流且收集器不具备CONCURRENT特性时,combiner方法返回的lambda表达式才会执行

如果收集器没有标为UNORDERED,那它仅在用于无序数据源时才可以并行归约

 

Collector.Characteristics  UNORDERED

表示不承诺按照操作顺序排列

Collector.Characteristics  IDENTITY_FINISH
表示中间结果容器类型与最终结果类型一致,此时finiser方法不会被调用

 

静态工厂方法

根据提供的给定条件创建 Collector

image_5b7bb60d_c4d

 

Collector  就是归约运算操作的一种抽象

 

image_5b7bb60d_72cc

首先要理解归约reduce的含义  也就是归纳转换成另外一种形式


想要进行归约运算,你先给出一个初始容器,作为中间结果容器

然后再给出迭代运算逻辑 也就是要如何归约  归约的逻辑  就是在这里 结果计算到中间结果容器中

针对于并行计算还需要一个合并的方式

中间结果肯定是为了方便计算,如果你最终想要的不是这种类型,我还可以给你转换下

 

Collector用 类型TAR 和四个方法将归约的过程逻辑化


T - 输入类型

A - 在收集过程中用于累积部分结果的对象类型

R - 返回类型  

Supplier supplier();  所以此方法提供了一个保存中间结果的对象 类型是A

BiConsumer accumulator();  不断迭代运算操作结果累计到中间结果上 类型为A   流类型为T

Function finisher();  最终的结果为A  还要根据实际情况是否转换为R

BinaryOperator combiner(); 用于合并计算

 

 

 

Collector工厂Collectors

 

image_5b7bb60d_2a98

提供了Collector的一些常用实现  比如

 

// 获取所有的name转换到List
List list = people.stream().map(Person::getName).collect(Collectors.toList());// 获取所有的name转换到Set
Set set = people.stream().map(Person::getName).collect(Collectors.toCollection(TreeSet::new));
// 元素转换为String 并且将他们通过", " 连接起来
String joined = things.stream()
.map(Object::toString)
.collect(Collectors.joining(", "));
//计算员工薪水之和
int total = employees.stream()
.collect(Collectors.summingInt(Employee::getSalary)));
// 按照部门对员工进行分组
Map> byDept
= employees.stream()
.collect(Collectors.groupingBy(Employee::getDepartment));
// 计算部门薪资和
Map totalByDept
= employees.stream()
.collect(Collectors.groupingBy(Employee::getDepartment,
Collectors.summingInt(Employee::getSalary)));
// 按照成绩是否通过把学生分为两组
Map> passingFailing =
students.stream()
.collect(Collectors.partitioningBy(s -> s.getGrade() >= PASS_THRESHOLD));

Collectors 中有一个静态内部类CollectorImpl  实现了CollectorImpl

预置的一些收集器都是通过CollectorImpl  返回的

/**
* Simple implementation class for {@code Collector}.
*
* @param the type of elements to be collected
* @param the type of the result
*/
static class CollectorImpl implements Collector {
private final Supplier supplier;
private final BiConsumer accumulator;
private final BinaryOperator
combiner;
private final Function finisher;
private final Set characteristics;CollectorImpl(Supplier
supplier,
BiConsumer accumulator,
BinaryOperator
combiner,
Function finisher,
Set characteristics) {
this.supplier = supplier;
this.accumulator = accumulator;
this.combiner = combiner;
this.finisher = finisher;
this.characteristics = characteristics;
}CollectorImpl(Supplier
supplier,
BiConsumer accumulator,
BinaryOperator
combiner,
Set characteristics) {
this(supplier, accumulator, combiner, castingIdentity(), characteristics);
}@Override
public BiConsumer accumulator() {
return accumulator;
}@Override
public Supplier
supplier() {
return supplier;
}
@Override
public BinaryOperator
combiner() {
return combiner;
}
@Override
public Function finisher() {
return finisher;
}
@Override
public Set characteristics() {
return characteristics;
}
}

 

Collectors中内置的  关于Collector  characteristics  特性的组合值

image_5b7bb60e_3f50

 

 

看一个例子

Collector> toList() {
return new CollectorImpl<>( (Supplier>) ArrayList::new,
List::add,
(left, right) -> { left.addAll(right); return left; },
CH_ID);
}

 

TAR分别是 T ?  List  也就是处理元素为T类型 返回结果为List  中间结果随意

ArrayList::new  返回List  作为中间结果,显然,跟返回结果一样,不需要调用finisher了

归约方式为 使用List.add方法不断地将集合中的元素添加到中间结果中

合并方式为直接将一个List addAll到另一个list  并且返回最终结果

因为不需要调用finisher  设置下特征 CH_ID

 

所以说只要按规矩实现了四个方法以及设置characteristics 就可以实现一个Collector

 

你可以使用Stream中

image_5b7bb60e_1304

调用Collectors 提供的一些Collector  或者你自己定义的

你还可以使用Stream中

image_5b7bb60e_4fc2

直接传递参数,显然并不是很直观 建议能不用就别用了 

 

 

 

 

 

 

 

 


推荐阅读
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • 本文介绍了闭包的定义和运转机制,重点解释了闭包如何能够接触外部函数的作用域中的变量。通过词法作用域的查找规则,闭包可以访问外部函数的作用域。同时还提到了闭包的作用和影响。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • Python正则表达式学习记录及常用方法
    本文记录了学习Python正则表达式的过程,介绍了re模块的常用方法re.search,并解释了rawstring的作用。正则表达式是一种方便检查字符串匹配模式的工具,通过本文的学习可以掌握Python中使用正则表达式的基本方法。 ... [详细]
  • 本文介绍了一个在线急等问题解决方法,即如何统计数据库中某个字段下的所有数据,并将结果显示在文本框里。作者提到了自己是一个菜鸟,希望能够得到帮助。作者使用的是ACCESS数据库,并且给出了一个例子,希望得到的结果是560。作者还提到自己已经尝试了使用"select sum(字段2) from 表名"的语句,得到的结果是650,但不知道如何得到560。希望能够得到解决方案。 ... [详细]
  • 本文详细介绍了Spring的JdbcTemplate的使用方法,包括执行存储过程、存储函数的call()方法,执行任何SQL语句的execute()方法,单个更新和批量更新的update()和batchUpdate()方法,以及单查和列表查询的query()和queryForXXX()方法。提供了经过测试的API供使用。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • 闭包一直是Java社区中争论不断的话题,很多语言都支持闭包这个语言特性,闭包定义了一个依赖于外部环境的自由变量的函数,这个函数能够访问外部环境的变量。本文以JavaScript的一个闭包为例,介绍了闭包的定义和特性。 ... [详细]
  • Html5-Canvas实现简易的抽奖转盘效果
    本文介绍了如何使用Html5和Canvas标签来实现简易的抽奖转盘效果,同时使用了jQueryRotate.js旋转插件。文章中给出了主要的html和css代码,并展示了实现的基本效果。 ... [详细]
  • Android自定义控件绘图篇之Paint函数大汇总
    本文介绍了Android自定义控件绘图篇中的Paint函数大汇总,包括重置画笔、设置颜色、设置透明度、设置样式、设置宽度、设置抗锯齿等功能。通过学习这些函数,可以更好地掌握Paint的用法。 ... [详细]
  • GetWindowLong函数
    今天在看一个代码里头写了GetWindowLong(hwnd,0),我当时就有点费解,靠,上网搜索函数原型说明,死活找不到第 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
author-avatar
一直都在囚禁
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有