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

时间:2022-09-20 22:21:33

Collector常见用法

 
 
常用形式为:   .collect(Collectors.toList())
collect()是Stream的方法
Collectors  是收集器Collector 的工厂方法,提供了一些常用的收集器 
比如
[四] java8 函数式编程 收集器浅析 收集器Collector常用方法 运行原理 内部实现
[四] java8 函数式编程 收集器浅析 收集器Collector常用方法 运行原理 内部实现

常用收集器概要

收集器 行为

toList()

将元素收集到一个 

List

中。

toSet()

将元素收集到一个 

Set

中。

toCollection()

将元素收集到一个 

Collection

中。

toMap(...)

将元素收集到一个 

Map

中,依据提供的映射函数将元素转换为键/值。

summingInt(ToIntFunction<? super T>)

给定值序列进行求和(还有 

long

和 

double

版本)

summarizingInt(ToIntFunction<T>)

给定值序列计算统计信息

sum


min


max


count

和 

average   (还有  long 和  double 版本)

reducing(...)

用于归约计算(通常用作下游收集器,比如用于 

groupingBy 或者partitioningBy 下游

partitioningBy(...)

按照predicate分为两组

groupingBy(...)

将元素分组
maxBy(Comparator<? super T> comparator) 最大值

minBy(Comparator<? super T> comparator)

最小值

mapping(Function<T,U>, Collector)

将提供的映射函数应用于每个元素,并使用指定的下游收集器(通常用作下游收集器本身,比如用于 

groupingBy

)进行处理。

joining()

假设元素为 

String

类型,将这些元素联结到一个字符串中(或许使用分隔符、前缀和后缀)。

counting()

计算元素数量。(通常用作下游收集器。)
averagingInt(ToIntFunction<? super T>) 平均数     (还有  long 和  double 版本)
 

收集器参数列表

toList()
toSet()
toCollection(Supplier<C>)
counting()
collectingAndThen(Collector<T, A, R>, Function<R, RR>)
summingInt(ToIntFunction<? super T>)
summingLong(ToLongFunction<? super T>)
summingDouble(ToDoubleFunction<? super T>)
maxBy(Comparator<? super T>)
minBy(Comparator<? super T>)
reducing(BinaryOperator<T>)
reducing(T, BinaryOperator<T>)
reducing(U, Function<? super T, ? extends U>, BinaryOperator<U>)
joining()
joining(CharSequence)
joining(CharSequence, CharSequence, CharSequence)
mapping(Function<? super T, ? extends U>, Collector<? super U, A, R>)
toMap(Function<? super T, ? extends K>, Function<? super T, ? extends U>)
toMap(Function<? super T, ? extends K>, Function<? super T, ? extends U>, BinaryOperator<U>)
toMap(Function<? super T, ? extends K>, Function<? super T, ? extends U>, BinaryOperator<U>, Supplier<M>)
toConcurrentMap(Function<? super T, ? extends K>, Function<? super T, ? extends U>)
toConcurrentMap(Function<? super T, ? extends K>, Function<? super T, ? extends U>, BinaryOperator<U>)
toConcurrentMap(Function<? super T, ? extends K>, Function<? super T, ? extends U>, BinaryOperator<U>, Supplier<M>)
groupingBy(Function<? super T, ? extends K>)
groupingBy(Function<? super T, ? extends K>, Supplier<M>, Collector<? super T, A, D>)
groupingBy(Function<? super T, ? extends K>, Collector<? super T, A, D>)
groupingByConcurrent(Function<? super T, ? extends K>)
groupingByConcurrent(Function<? super T, ? extends K>, Supplier<M>, Collector<? super T, A, D>)
groupingByConcurrent(Function<? super T, ? extends K>, Collector<? super T, A, D>)
partitioningBy(Predicate<? super T>)
partitioningBy(Predicate<? super T>, Collector<? super T, A, D>)
averagingDouble(ToDoubleFunction<? super T>)
averagingInt(ToIntFunction<? super T>)
averagingLong(ToLongFunction<? super T>)
summarizingDouble(ToDoubleFunction<? super T>)
summarizingInt(ToIntFunction<? super T>)
summarizingLong(ToLongFunction<? super T>)
 

收集器详解


Collector
[四] java8 函数式编程 收集器浅析 收集器Collector常用方法 运行原理 内部实现
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> characteristics()  方法可以访问
Collector.Characteristics  CONCURRENT 
表示中间结果只有一个,即使在并行流的情况下
所以只有在并行流且收集器不具备CONCURRENT特性时,combiner方法返回的lambda表达式才会执行
如果收集器没有标为UNORDERED,那它仅在用于无序数据源时才可以并行归约
 
Collector.Characteristics  UNORDERED
表示不承诺按照操作顺序排列
Collector.Characteristics  IDENTITY_FINISH
表示中间结果容器类型与最终结果类型一致,此时finiser方法不会被调用
 
静态工厂方法
根据提供的给定条件创建 Collector
[四] java8 函数式编程 收集器浅析 收集器Collector常用方法 运行原理 内部实现
 

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


[四] java8 函数式编程 收集器浅析 收集器Collector常用方法 运行原理 内部实现
首先要理解归约reduce的含义  也就是归纳转换成另外一种形式
想要进行归约运算,你先给出一个初始容器,作为中间结果容器
然后再给出迭代运算逻辑 也就是要如何归约  归约的逻辑  就是在这里 结果计算到中间结果容器中
针对于并行计算还需要一个合并的方式
中间结果肯定是为了方便计算,如果你最终想要的不是这种类型,我还可以给你转换下
 

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

T - 输入类型
A - 在收集过程中用于累积部分结果的对象类型
R - 返回类型  
Supplier<A> supplier();  所以此方法提供了一个保存中间结果的对象 类型是A
BiConsumer<A, T> accumulator();  不断迭代运算操作结果累计到中间结果上 类型为A   流类型为T
Function<A, R> finisher();  最终的结果为A  还要根据实际情况是否转换为R
BinaryOperator<A> combiner(); 用于合并计算
 
 

Collector工厂Collectors


[四] java8 函数式编程 收集器浅析 收集器Collector常用方法 运行原理 内部实现
提供了Collector的一些常用实现  比如
// 获取所有的name转换到List<String>中
List<String> list = people.stream().map(Person::getName).collect(Collectors.toList()); // 获取所有的name转换到Set<String>中
Set<String> 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<Department, List<Employee>> byDept
= employees.stream()
.collect(Collectors.groupingBy(Employee::getDepartment));
// 计算部门薪资和
Map<Department, Integer> totalByDept
= employees.stream()
.collect(Collectors.groupingBy(Employee::getDepartment,
Collectors.summingInt(Employee::getSalary)));
// 按照成绩是否通过把学生分为两组
Map<Boolean, List<Student>> passingFailing =
students.stream()
.collect(Collectors.partitioningBy(s -> s.getGrade() >= PASS_THRESHOLD));
Collectors 中有一个静态内部类CollectorImpl  实现了CollectorImpl
预置的一些收集器都是通过CollectorImpl  返回的
/**
* Simple implementation class for {@code Collector}.
*
* @param <T> the type of elements to be collected
* @param <R> the type of the result
*/
static class CollectorImpl<T, A, R> implements Collector<T, A, R> {
private final Supplier<A> supplier;
private final BiConsumer<A, T> accumulator;
private final BinaryOperator<A> combiner;
private final Function<A, R> finisher;
private final Set<Characteristics> characteristics;
CollectorImpl(Supplier<A> supplier,
BiConsumer<A, T> accumulator,
BinaryOperator<A> combiner,
Function<A,R> finisher,
Set<Characteristics> characteristics) {
this.supplier = supplier;
this.accumulator = accumulator;
this.combiner = combiner;
this.finisher = finisher;
this.characteristics = characteristics;
} CollectorImpl(Supplier<A> supplier,
BiConsumer<A, T> accumulator,
BinaryOperator<A> combiner,
Set<Characteristics> characteristics) {
this(supplier, accumulator, combiner, castingIdentity(), characteristics);
} @Override
public BiConsumer<A, T> accumulator() {
return accumulator;
} @Override
public Supplier<A> supplier() {
return supplier;
}
@Override
public BinaryOperator<A> combiner() {
return combiner;
}
@Override
public Function<A, R> finisher() {
return finisher;
}
@Override
public Set<Characteristics> characteristics() {
return characteristics;
}
}
Collectors中内置的  关于Collector  characteristics  特性的组合值
[四] java8 函数式编程 收集器浅析 收集器Collector常用方法 运行原理 内部实现
 
 
看一个例子
Collector<T, ?, List<T>> toList() {
return new CollectorImpl<>( (Supplier<List<T>>) ArrayList::new,
List::add,
(left, right) -> { left.addAll(right); return left; },
CH_ID);
}
TAR分别是 T ?  List<T>  也就是处理元素为T类型 返回结果为List<T>  中间结果随意
ArrayList::new  返回List<T>  作为中间结果,显然,跟返回结果一样,不需要调用finisher了
归约方式为 使用List.add方法不断地将集合中的元素添加到中间结果中
合并方式为直接将一个List addAll到另一个list  并且返回最终结果
因为不需要调用finisher  设置下特征 CH_ID
 
所以说只要按规矩实现了四个方法以及设置characteristics 就可以实现一个Collector
 
你可以使用Stream中
[四] java8 函数式编程 收集器浅析 收集器Collector常用方法 运行原理 内部实现
调用Collectors 提供的一些Collector  或者你自己定义的
你还可以使用Stream中
[四] java8 函数式编程 收集器浅析 收集器Collector常用方法 运行原理 内部实现
直接传递参数,显然并不是很直观 建议能不用就别用了 
 
 
 
 
 
 
 
 

[四] java8 函数式编程 收集器浅析 收集器Collector常用方法 运行原理 内部实现的更多相关文章

  1. Java8函数式编程探秘

    引子 将行为作为数据传递 怎样在一行代码里同时计算一个列表的和.最大值.最小值.平均值.元素个数.奇偶分组.指数.排序呢? 答案是思维反转!将行为作为数据传递. 文艺青年的代码如下所示: public ...

  2. Python学习笔记(四)函数式编程

    高阶函数(Higher-order function) Input: 1 abs Output: 1 <function abs> Input: 1 abs(-10) Output: 1 ...

  3. 关于Java8函数式编程你需要了解的几点

    函数式编程与面向对象的设计方法在思路和手段上都各有千秋,在这里,我将简要介绍一下函数式编程与面向对象相比的一些特点和差异. 函数作为一等公民 在理解函数作为一等公民这句话时,让我们先来看一下一种非常常 ...

  4. Java8 函数式编程详解

    Java8 函数式编程详解 Author:Dorae Date:2017年11月1日23:03:26 转载请注明出处 说起Java8,可能很多人都已经知道其最大的改进,就是引入了Lambda表达式与S ...

  5. &lbrack;2017&period;02&period;23&rsqb; Java8 函数式编程

    以前学过Haskell,前几天又复习了其中的部分内容. 函数式编程与命令式编程有着不一样的地方,函数式编程中函数是第一等公民,通过使用少量的几个数据结构如list.map.set,以及在这些数据结构上 ...

  6. &lbrack;一&rsqb; java8 函数式编程入门 什么是函数式编程 函数接口概念 流和收集器基本概念

      本文是针对于java8引入函数式编程概念以及stream流相关的一些简单介绍 什么是函数式编程?   java程序员第一反应可能会理解成类的成员方法一类的东西 此处并不是这个含义,更接近是数学上的 ...

  7. &lbrack;零&rsqb;java8 函数式编程入门官方文档中文版 java&period;util&period;stream 中文版 流处理的相关概念

    前言 本文为java.util.stream 包文档的译文 极其个别部分可能为了更好理解,陈述略有改动,与原文几乎一致 原文可参考在线API文档 https://docs.oracle.com/jav ...

  8. java8函数式编程(转载)

    1. 概述 1.1 函数式编程简介 我们最常用的面向对象编程(Java)属于命令式编程(Imperative Programming)这种编程范式.常见的编程范式还有逻辑式编程(Logic Progr ...

  9. 重识Java8函数式编程

    前言 最近真的是太忙忙忙忙忙了,很久没有更新文章了.最近工作中看到了几段关于函数式编程的代码,但是有点费解,于是就准备总结一下函数式编程.很多东西很简单,但是如果不总结,可能会被它的各种变体所困扰.接 ...

随机推荐

  1. vim快捷键

    #vim  filename :scriptname //查看vim加载了哪些脚本 :set nu //设置行号 :set tabstop=4 //设置一个tab为4个空格长度 :set ai //设 ...

  2. Javascript初学篇章&lowbar;8(事件)

    事件 HTML 事件是发生在 HTML 元素上的事情.例如用户点击按钮时,点击也是一个事件.事件可以用于处理表单验证,用户输入,用户行为及浏览器动作,如: 页面加载时触发事件 页面关闭时触发事件 用户 ...

  3. 【转】PowerShell入门(十):使用配置文件

    转至:http://www.cnblogs.com/ceachy/archive/2013/03/01/PowerShell_Profile.html 在命令行中定义别名.变量和函数,只是将它们添加在 ...

  4. 物料分类账 &lbrack;COML&rsqb; PART 2 - 总体流程

    核心流程概要: [1]. 分类账在物料主数据的影响 首先描述下SAP中物料价格的 物料主数据相关的几个点: q价格控制(Price Control): 决定物料计价方式. S 标准价格(Standar ...

  5. 快捷键accesskey

    <!DOCTYPE html> <html> <body> <a href="http://www.w3school.com.cn/html/&qu ...

  6. quick-cocos2d-x教程8&colon;程序框架内lib文件夹分析

    lib文件夹是如今全部文件夹中最复杂的,包括了整个运行所需的库文件.我们简单看下,在开发初期,不须要深入到这个库里去研究 cocos2d-x 文件夹就是c++版的原始文件 framework_prec ...

  7. jpa 解决org&period;hibernate&period;lazyinitializationexception could not initialize proxy - no session

    org.hibernate.LazyInitializationException: could not initialize proxy [org.alan.entity.SysUser#1] - ...

  8. Basestation函数解析(一)

    ---恢复内容开始--- 1._tmain   _tmain()是微软操作系统(windows)提供的对unicode字符集和ANSI字符集进行自动转换用的程序入口点函数. 首先,这个_tmain() ...

  9. Passing address of non-local object to &lowbar;&lowbar;autoreleasing parameter for write-back

    在希望通过函数的參数返回Objective-C对象的时候.遇到了这个问题 错误代码例如以下: - (void)methodA:(NSString **)string<span style=&qu ...

  10. PyQt5教程——菜单和工具栏(3)

    PyQt5中的菜单和工具栏 在这部分的PyQt5教程中,我们将创建菜单和工具栏.菜单式位于菜单栏的一组命令操作.工具栏是应用窗体中由按钮和一些常规命令操作组成的组件. 主窗口 QMainWindow类 ...