stream的collectors

起因的话,新进公司,看见了一段有意思的代码。

public final class MyCollectors {
   
    private MyCollectors() {

    }

    static final Set<Collector.Characteristics> CH_ID = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.IDENTITY_FINISH));


    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;
        }
    }

    @SuppressWarnings("unchecked")
    private static <I, R> Function<I, R> castingIdentity() {
        return i -> (R) i;
    }

 
    public static <T> Collector<T, ?, Page<T>> toPage() {
        return new CollectorImpl<>((Supplier<Page<T>>) () -> new Page<T>(), Page::add, (left, right) -> {
            left.addAll(right);
            left.setTotal(1);
            return left;
        }, CH_ID);
    }
}

这个,我们基本也能猜到这个代码主要用处,应该是toPage,应该是将list转换为page对象。

但是我们平常的用法的话,基本都是自己构建对象,自己塞。或者stream的map,然后我们用一个枚举类,常量类的function<list,Page>这样的来转换list到page。这里实现了一个自己的收集器,就比较新颖。

但是我有点搞不懂各个参数的具体意义。那怎么办呢?我就想到,我应该是哪里看到过博客,果然还是得瞎几把看看,这样起码知道讲的是什么,要去哪找。

深度探秘 Java 8 函数式编程(上)_mb60f8d1355165a的技术博客_51CTO博客

可以进去看看,

他这里说的是,

四要素
一个聚合器的实现,通常需要提供四要素:

一个结果容器的初始值提供器 supplier ;

一个用于将每次二元操作的中间结果与结果容器的值进行操作并重新设置结果容器的累积器 accumulator ;

一个用于对Stream元素和中间结果进行操作的二元操作符 combiner ;

一个用于对结果容器进行最终聚合的转换器 finisher(可选) 。

那我们也实习一个自己的收集器,就实现一个累加器吧。

public class FiboCollector implements Collector<Integer, List<Integer>, Integer> {

    public Supplier<List<Integer>> supplier() {
        return () -> {
            List<Integer> result = new ArrayList<>();
            return result;
        };
    }

    @Override
    public BiConsumer<List<Integer>, Integer> accumulator() {
        return (res, num) -> {
            if(res.size()==0){
                res.add(num);
            }else{
                Integer integer = res.get(0);
                res.set(0,integer+num);
            }
        };
    }

    @Override
    public BinaryOperator<List<Integer>> combiner() {

        return (left, right) -> {
            System.out.println(left);
            System.out.println(right);
            return left;
        };
    }

    @Override
    public Function<List<Integer>, Integer> finisher() {
        return x->{ return x.get(0);};
    }

    @Override
    public Set<Characteristics> characteristics() {
        return Collections.emptySet();
    }

    public static void main(String[] args) {

        Integer collect = Arrays.asList(2, 2, 3, 4, 5, 6, 7, 8, 9, 10).stream().collect(new FiboCollector());
        System.out.println(collect);
    }
}

这里容器的话,supplier按道理应该返回intteger的,但是考虑到累加器accumulator的话,因为是一个没有返回值的,那么应该是覆盖的,但是感觉不太对,然后想起来那我用finisher最后处理的时候,返回interger不就好了。之前容器用list不就好了,于是就写出这么一段代码。但是问题又来了combiner是干嘛用的。

一个用于对Stream元素和中间结果进行操作的二元操作符 combiner ;

不太对吧,我debug看,也没有走到这段代码。

遇事不决就百度。

(66条消息) 关于java Stream中的reduce使用和为什么要有combiner_Cyberin的博客-CSDN博客

图片讲的很清楚了,就是没用并行流之前,用的combiner,如果用parallel,应该是几个元素执行完combiner后,要合并的是,你要做的操作。那么我们肯定是两个list拿第一个元素,然后加完以后,返回一个list。

public class FiboCollector implements Collector<Integer, List<Integer>, Integer> {

    public Supplier<List<Integer>> supplier() {
        return () -> {
            List<Integer> result = new ArrayList<>();
            return result;
        };
    }

    @Override
    public BiConsumer<List<Integer>, Integer> accumulator() {
        return (res, num) -> {
            if(res.size()==0){
                res.add(num);
            }else{
                Integer integer = res.get(0);
                res.set(0,integer+num);
            }
        };
    }

    @Override
    public BinaryOperator<List<Integer>> combiner() {

        return (left, right) -> {
            System.out.println(left);
            System.out.println(right);
            int i = left.get(0) + right.get(0);
            List<Integer> data =new ArrayList<>();
            data.add(i);
            return data;
        };
    }

    @Override
    public Function<List<Integer>, Integer> finisher() {
        return x->{ return x.get(0)+;};
    }

    @Override
    public Set<Characteristics> characteristics() {
        return Collections.emptySet();
    }

    public static void main(String[] args) {

        Integer collect = Arrays.asList(2, 2, 3, 4, 5, 6, 7, 8, 9, 10).stream().parallel().collect(new FiboCollector());
        System.out.println(collect);
    }
}

执行也可以看到,打印出sout了。

一个用于parallel 对中间结果进行操作合并操作的二元操作符 combiner ;

这样每个元素我们就知道怎么实现了,那么我们就基本知道套路了。

我们可以去看看collects。集合聚合器 toSet(), 字符串连接器 joining(),以及列表求和(summingXXX)、最大(maxBy)、最小值(minBy)等都是这个套路。

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

那么我们能用他干嘛,我这里的话,只能想到上面的list转page。算是扩展点吧。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/18145.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

从点赞到数字货币:揭秘Diem币与Facebook的联系

大家都知道Facebook是一个全球知名的社交媒体平台&#xff0c;但你是否听说过与Facebook有关的数字货币Diem币呢&#xff1f;或许你会想&#xff0c;从点赞到数字货币&#xff0c;这是怎么回事&#xff1f;别着急&#xff0c;让我们一起揭秘Diem币与Facebook的联系。 首先&…

rk平台调试音频(从驱动到apk)

需要实现的功能&#xff1a; 输入&#xff1a;hdmiin、uvc、mic可以实时切换 输出&#xff1a;耳机和HDMI OUT同时输出声音 这里注意&#xff1a;mic是存在hedset情况&#xff0c;4节耳机&#xff0c;即可输出又可输出同时进行 开发情况&#xff1a; 一、先熟悉大致的Andro…

ArcMap最短路径分析和网络数据集的构建

打断相交点 1.单击【编辑器】工具条上的编辑工具。 2.选择要在交叉点处进行分割的线要素。 3.单击【高级编辑】工具条上的打断相交线工具。 4.默认或可输入拓扑容差。 5.单击确定。 结果:所选线在相交处分割为多个新要素。“打断”操作还会移除叠置的线段-例如&#xff0…

怎么控制别人的电脑屏幕?

为什么需要控制别人的屏幕&#xff1f; 我们不可避免地会遇到一些情况&#xff0c;比如我们需要为我们的朋友、同事或家人提供有关 IT 相关问题的帮助&#xff0c;如果他们不知道它该怎么处理这些问题该怎么办呢&#xff1f; 这时&#xff0c;我们可能需要用我们的电脑…

测试20K要什么水平?25岁测试工程师成功斩下offer(附面试题)

年少不懂面试经&#xff0c;读懂已是测试人。 大家好&#xff0c;我是一名历经沧桑&#xff0c;看透互联网行业百态的测试从业者&#xff0c;经过数年的勤学苦练&#xff0c;精钻深研究&#xff0c;终于从初出茅庐的职场新手成长为现在的测试老鸟&#xff0c;早已看透了面试官…

三维数据学习笔记:ply数据内容介绍

目录 前言1. 三维数据的组成1.1 点云数据1.2 网格数据 2. ply数据内容2.1 属性2.1.1 文本描述属性2.1.2 数据描述属性2.1.2.1 顶点(vertex)2.1.2.2 面(face)2.1.2.3 相机(camera) 2.2 数据2.2.1 顶点(vertex)2.2.2 面(face)2.2.3 相机(camera) 3. 示例3.1 示例13.2 示例2 前言 …

Java基础(十七)File类与IO流

1. java.io.File类的使用 1.1 概述 File类及本章下的各种流&#xff0c;都定义在java.io包下。一个File对象代表硬盘或网络中可能存在的一个文件或者文件目录&#xff08;俗称文件夹&#xff09;&#xff0c;与平台无关。&#xff08;体会万事万物皆对象&#xff09;File 能新…

JDK17新特性之--JDK9到JDK17 String 新增的新方法

JDK9之后对String底层存储数据结构进行了重大的修改1&#xff0c;同步也增加了许多新的方法&#xff0c;主要有Text Blocks、chars()、codePoints()、describeConstable()、formatted()、indent()、isBlank()、isEmpty()、lines()、repeat()、strip()、stripLeading()、stripIn…

DolphinScheduler 3.1.4详细教程

文章目录 第一章 DolphinScheduler介绍1.1 关于DolphinScheduler1.2 特性1.3 名词解释1.3.1 名词解释1.3.2 模块介绍 第二章 DolphinScheduler系统架构2.1 系统架构图2.2 架构说明该服务包含&#xff1a; 2.3 启动流程活动图2.4 架构设计思想2.4.1 去中心化vs中心化2.4.1.1 中心…

北京地铁:充分发挥数据价值,全面提升业财融合能力

4月19日-4月21日&#xff0c;一年一度的用友BIP技术大会圆满召开。来自行业领先企业的CIO/CDO、生态伙伴、开发者、分析师、媒体等共聚北京用友产业园&#xff0c;了解最新技术发展趋势、探讨行业热点话题。会上&#xff0c;北京地铁运营有限公司&#xff08;以下简称“北京地铁…

使用 ChatGPT 辅助学习——为自己找一个老师

我们每个人都有许多标签&#xff0c;例如高中生、成绩中等、文科&#xff0c;根据这些标签我和其他拥有相同标签的人分配了相同的教程、班级和老师&#xff0c;这可以带来效率上的提升&#xff0c;因为同一份教程、老师就可以服务几十上百人&#xff0c;而无须为每个人定制&…

2023年腾讯云轻量服务器性能评测

腾讯云轻量应用服务器性能评测 轻量应用服务器是腾讯云推出的一款开箱即用的轻量级的云服务器&#xff0c;轻量服务器CPU内存带宽配置更高&#xff0c;价格却又很便宜&#xff0c;很多同学认为是不是轻量应用服务器性能不行呀&#xff0c;轻量服务器和云服务器有什么区别&…

浪潮盒子IPBS9505-多遥控版-S905L/M2芯片-安卓4.4.2-线刷固件包

浪潮盒子IPBS9505-多遥控版-S905L&#xff0f;M2芯片-安卓4.4.2-线刷固件包-内有教程和短接点-当贝纯净桌面。 特点&#xff1a; 1、适用于对应型号的电视盒子刷机&#xff1b; 2、开放原厂固件屏蔽的市场安装和u盘安装apk&#xff1b; 3、修改dns&#xff0c;三网通用&…

因子挖掘框架cs优缺点介绍和使用说明

cs框架的优点和缺点 优点和ts一样,就是速度非常快缺点有好几个:必须使用根据过去一定天数计算因子值,持有一定天数之后再平衡的模式;必须使用连续的数据,如果是期货期权等需要合成连续数据。资金不足的时候不会拒单。cs框架使用方法 设计理念 计算因子由用户进行计算,因…

Springboot +Flowable,任务认领和回退(一)

一.简介 有的时候&#xff0c;一个任务节点会存在多个候选人&#xff0c;例如&#xff1a;张三提交一个任务&#xff0c;这个任务即可以由李四处理&#xff0c;又可以由王五处理&#xff0c;那么针对这种多个任务候选人的情况&#xff0c;该如何处理&#xff1f; 二.绘制流程…

项目管理-数据管理能力DCMM模型

DCMM 数据管理能力成熟度评估模型简介 DCMM&#xff08;Data Management Capability Maturity Assessment Model&#xff0c;数据管理能力成熟度评估模型&#xff09;是我国首个数据管理领域国家标准。该标准将组织对象的数据管理划分为八大能力域&#xff08;数据战略、数据治…

python4delphi之初体验

最近需要做一个excel导入的工具, excel表格是python的强项,于是想delphi结合python实现 delphi环境xe2 python 3.6.6 上图可以看到,真的很爽,我在vscode写python脚本,然后给delphi调用 读取了一个excel文件,打印出了列头。 最爽的是,我在没wps,office环境的机…

( “图“ 之 二分图 ) 785. 判断二分图 ——【Leetcode每日一题】

❓785. 判断二分图 难度&#xff1a;中等 存在一个 无向图 &#xff0c;图中有 n 个节点。其中每个节点都有一个介于 0 到 n - 1 之间的唯一编号。给你一个二维数组 graph &#xff0c;其中 graph[u] 是一个节点数组&#xff0c;由节点 u 的邻接节点组成。形式上&#xff0c;…

MySQL一次大量内存消耗的跟踪

GreatSQL社区原创内容未经授权不得随意使用&#xff0c;转载请联系小编并注明来源。GreatSQL是MySQL的国产分支版本&#xff0c;使用上与MySQL一致。文章来源&#xff1a;GreatSQL社区原创 线上使用MySQL8.0.25的数据库&#xff0c;通过监控发现数据库在查询一个视图(80张表的u…

xcode打包导出ipa

xcode打包导出ipa 众所周知&#xff0c;在开发苹果应用时需要使用签名&#xff08;证书&#xff09;才能进行打包安装苹果IPA&#xff0c;作为刚接触ios开发的同学&#xff0c;只是学习ios app开发内测&#xff0c;并没有上架appstore需求&#xff0c;对于苹果开发者账号认证需…
最新文章