带你了解 Java 8 Stream:掌握流处理中的收集器技巧

Java 8 引入的 Stream 极大地简化了集合数据的处理,提供了一种现代、函数式的方式来处理数据。然而,在处理流时,我们经常需要将流的结果汇总到集合中或者进行各种统计计算。这就是收集器(Collectors)发挥作用的地方。本文将深入探讨 Java 8 Stream 中的收集器,介绍收集器的各种用法和技巧,帮助你更好地利用收集器处理数据。

什么是收集器(Collectors)

收集器是 Stream 提供的一个重要功能,用于将流的元素收集到一个结果容器中。通过使用收集器,可以让代码更加方便的进行简化与重用。其内部主要核心是通过 Collectos 完成更加复杂的计算转换从而获取到最终结果。

Java 8 在 Collectors 类中预定义了多个用于收集的方法,使得我们可以轻松地对流的元素进行汇总、分组、分区以及其他各种操作。

常见的收集器用法

通过 toList 将元素收集到集合中

List<String> names = peopleStream.map(Person::getName)
                                 .collect(Collectors.toList());

通过 counting 统计集合总数

Long collect = studentList.stream().collect(Collectors.counting());

通过 maxBy 和 minBy 获取最大值最小值

Optional<Student> optional = studentList.stream().collect(Collectors.maxBy(Comparator.comparing(Student::getAge));)

if (optional.isPresent()){
    Student student = optional.get();
    System.out.println(student);
}

通过 summingLnt 进行数据汇总

Integer collect  = peopleStream.collect(Collectors.summingLnt(Person::getAge));

int sum = peopleStream.mapToInt(Person::getAge).sum();

通过 averagingLnt 进行平均值获取

Double collect  = peopleStream.collect(Collectors.averagingLnt(Person::getAge));

其内部是在收集过程中,对所有年龄进行累加,最后除以平
均值

通过 joining 进行数据拼接

Person collect  = peopleStream.collect(Collectors.joining());

这种方式相当于将流中每一个元素的name属性获取映射,内部通过StringBuilder来把每一个映射的值进行拼接。

通过 groupingBy 将数据进行分组

Map<Integer,List<Student>> map = peopleStream.collect(Collectors.groupingBy(Person::getAge));

自定义收集器

已经通过Collectors中提供的静态方法,完成了诸多的收集器操作,虽然它本身提供了诸多方法,但是不一定能够覆盖日常开发中的所有需求,因此,有时还需要我们根据自身的业务去自定义收集器的实现。通过实现 Collector 接口,我们可以完全掌控收集的过程。

源码分析

根据源码,Collector 接口需要三个参数。

  • T: 流中要收集的元素类型
  • A: 累加器的类型
  • R:收集的结果类型

如果想要自定义收集器,需要实现 Collector 接口中的五个方法 Supplier、Accumulator、finisher、combiner、characteristics

  • supplier:用于创建一个容器,在调用它时,需要创建一个空的累加器实例,供后续方法使用。
  • accumulator:基于supplier中创建的累加容器,进行累加操作。
  • finisher:当遍历完流后,在其内部完成最终转换,返回一个最终结果。
  • combiner:用于在并发情况下,将每个线程的容器进行合并。
  • characteristics:用于定义收集器行为,如是否可以并行或使用哪些优化。其本身是一个枚举,内部有三个值,分别为:
    • CONCURRENT:表明收集器是并行的且只会存在一个中间容器。
    • UNORDERED:表明结果不受流中顺序影响,收集是无序的。
    • IDENTITY_FINISH:表明累积器的结果将会直接作为归约的最终结果,跳过finisher()。

实战示例:收集合格的学生

  • 定义自定义收集器
package com.jdk8.features.stream.collector;

import com.jdk8.features.lambda.Student;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collector;
public class MyCollector implements Collector<Student, List<Student>,List<Student>> {

  @Override
  public Supplier<List<Student>> supplier() {
    return ArrayList::new;
  }

  @Override
  public BiConsumer<List<Student>, Student> accumulator() {
    return ((studentList, student) -> {
      if (student.getIsPass()){
        studentList.add(student);
      }
    });
  }

  @Override
  public BinaryOperator<List<Student>> combiner() {
    return null;
  }

  @Override
  public Function<List<Student>, List<Student>> finisher() {
    return Function.identity();
  }

  @Override
  public Set<Characteristics> characteristics() {
    return EnumSet.of(Characteristics.IDENTITY_FINISH,Characteristics.UNORDERED);
  }
}
  • 使用自定义收集器
import com.jdk8.features.lambda.Student;
import java.util.ArrayList;
import java.util.List;

public class MyCollectorDemo {

  public static void main(String[] args) {

    List<Student> studentList = new ArrayList<>();
    studentList.add(new Student(1,"张三",18,19));
    studentList.add(new Student(2,"李四",19,18));
    studentList.add(new Student(3,"王五",20,21));
    studentList.add(new Student(4,"赵六",21,80));

    List<Student> list = studentList.stream().collect(new MyCollector());
    System.out.println(list);
  }
}

结语

掌握收集器的使用是精通 Java 8 Stream 不可或缺的一部分。在处理流数据时,收集器可以帮助我们更轻松地完成数据的汇总、分组、分区等操作。通过本文的介绍,相信你已经对收集器有了更深入的了解,并能够在实际项目中灵活运用收集器的各种技巧。让我们在流处理的旅程中更加游刃有余!

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

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

相关文章

直播系统源码协议探索篇(二):网络套接字协议WebSocket

上一篇我们分析了直播平台的会话初始化协议SIP&#xff0c;他关乎着直播平台的实时通信和多方互动技术的实现&#xff0c;今天我们来讲另一个协议&#xff0c;叫网络套接字协议WebSocket&#xff0c;WebSocket基于TCP在客户端与服务器建立双向通信的网络协议&#xff0c;并且可…

React项目build打包后,页面空白的解决方案

问题描述&#xff1a; React项目执行 build 命令后&#xff0c;在本地服务器打开页面 是空白的&#xff0c;而且控制台报错 如下图所示 解决方法 打开根目录下的 package.json 文件&#xff0c;添加如下代码 {"name": "testproject","version"…

火山引擎发布自研视频编解码芯片 压缩效率提升30%

8月22日&#xff0c;火山引擎视频云宣布其自研的视频编解码芯片已成功出片。经验证&#xff0c;该芯片的视频压缩效率相比行业主流硬件编码器可提升30%以上&#xff0c;未来将服务于抖音、西瓜视频等视频业务&#xff0c;并将通过火山引擎视频云开放给企业客户。 火山引擎总裁…

vue3安装组件

如何创建vue项目链接&#xff1a;http://t.csdn.cn/tX8wY 新建vue项目如何配置&#xff1a;http://t.csdn.cn/YLdTG 我们这里拿vant组件演示 首先安装组件库 # Vue 3 项目&#xff0c;安装最新版 Vant npm i vant 可以在package.json查看 我们找到main.js 按钮举例 写入自…

微信小程序路由以及跳转页面传递参数

路由 在app.json的pages里面写 "pages/页面/页面" 直接保存pages直接生成非常方便 跳转页面 wx.navigateTo() 保留当前页面&#xff0c;跳转到应用内的某个非tabBar页面。 <text bindtap"daka">点击</text> daka:function () {wx.navigateTo…

关于chromedriver.exe一系列问题的解决办法

最新 chromedriver.exe下载地址&#xff1a;https://googlechromelabs.github.io/chrome-for-testing/#stable 下载最新版本的 chromedriver.exe 将其解压在 python.exe 同目录下&#xff0c;以及Chrome 的路径下 例如&#xff1a; C:\Program Files\Google\Chrome\Applicati…

校企合作 | 大势智慧受邀参与北斗共同体建设

8月16日&#xff0c;长江工业职业学院&#xff08;后简称“长江工院”&#xff09;副校长刘文胜&#xff0c;质管处处长黄世涛&#xff0c;测绘信息工程系党总支书记刘飞、系副主任陈志兰、系教师陈文玲一行莅临武汉大势智慧科技有限公司&#xff08;后简称“大势智慧”&#x…

ONLYOFFICE协作空间服务器如何一键安装自托管私有化部署

ONLYOFFICE协作空间服务器如何一键安装自托管私有化部署 如何在 Ubuntu 上部署 ONLYOFFICE 协作空间社区版&#xff1f;https://blog.csdn.net/m0_68274698/article/details/132069372?ops_request_misc&request_id&biz_id102&utm_termonlyoffice%20%E5%8D%8F%E4…

(动态规划) 剑指 Offer 42. 连续子数组的最大和 ——【Leetcode每日一题】

❓ 剑指 Offer 42. 连续子数组的最大和 难度&#xff1a;简单 输入一个整型数组&#xff0c;数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。 要求时间复杂度为 O(n)。 示例1: 输入: nums [-2,1,-3,4,-1,2,1,-5,4] 输出: 6 解释: 连续子数组 [4,-1…

springMVC Unix 文件参数变更漏洞修复

错误信息如下&#xff1a; 解决方案&#xff1a; 原因&#xff1a;未对用户输入正确执行危险字符清理 未检查用户输入中是否包含“…”&#xff08;两个点&#xff09;字符串&#xff0c;比如 url 为 /login?action…/webapps/RTJEKSWTN26635&typerandomCode cookie为Coo…

ast在python架构中的使用

AST学习 AST简介&#xff1a; AST(Abstract syntac tree)是编译原理中的概念&#xff0c;是对源代码语法结构的一种抽象表示&#xff0c;它以树的形式表现编程语言的语法结构&#xff0c;树上的每个节点都表示源代码中的一种结构。 下面的代码展示了以demo.py中的ast语法&…

刷视频看到的联通流量卡广告,19元210G能买吗?

现在为了争夺客户资源&#xff0c;三大运营商纷纷发力&#xff0c;推出了各种优惠套餐&#xff0c;就比如&#xff1a;前段时间电信推出29元155G长期套餐&#xff0c;移动29元135G本地套餐&#xff0c;广电19元192G套餐。 当然&#xff0c;联通也是不甘示弱&#xff0c;也跟上…

简单版的数组实现哈希表

package com.wei.mybatisflex;import java.util.ArrayList; import java.util.List;/*** 用数组实现哈希表*/ public class ArrayToHash {/*** 键值对定义*/class Pair{private int key;private String val;public Pair(int key, String val) {this.key key;this.val val;}}p…

WX1860- ngbe-1.2.5 xdp程序在路由模式下,使用iperf工具测试数据包不转发,用jmeter可以

本地验证时重定向iperf包有出现calltrace错误&#xff0c;经推断&#xff0c;系统PAGE_SIZE<8k时可能出现&#xff08;getconf PAGE_SIZE指令可查看&#xff09;&#xff0c;按下图将ngbe_main.c的2350行ngbe_rx_bufsz改为ngbe_rx_pg_size可修复。其次&#xff0c;需要将加载…

Apollo自动驾驶:引领未来的智能出行

自动驾驶技术正日益成为当今科技领域的焦点&#xff0c;它代表着未来出行的一大趋势&#xff0c;而Baidu公司推出的Apollo自动驾驶平台则在这一领域中展现出强大的领导地位。本文将深入探讨Apollo自动驾驶技术的关键特点、挑战以及它对未来智能出行的影响。 Apollo自动驾驶平台…

机器学习算法的选择和优化技巧

文章目录 机器学习算法的选择1. 问题类型&#xff1a;2. 数据规模&#xff1a;3. 特征空间&#xff1a;4. 数据质量&#xff1a; 机器学习算法的优化技巧1. 特征工程&#xff1a;2. 超参数调优&#xff1a;3. 集成方法&#xff1a;4. 模型调优&#xff1a; 代码示例&#xff1a…

全流程R语言Meta分析核心技术教程

详情点击链接&#xff1a;全流程R语言Meta分析核心技术教程 一&#xff0c;Meta分析的选题与检索 1、Meta分析的选题与文献检索 1)什么是Meta分析&#xff1f; 2)Meta分析的选题策略 3)精确检索策略&#xff0c;如何检索全、检索准 4)文献的管理与清洗&#xff0c;如何制定文…

一文了解汽车芯片的分类及用途介绍

汽车芯片按其功能可分为控制类&#xff08;MCU和AI芯片&#xff09;、功率类、传感器和其他&#xff08;如存储器&#xff09;四种类型。市场基本被国际巨头所垄断。人们常说的汽车芯片是指汽车里的计算芯片&#xff0c;按集成规模可分为MCU芯片和AI芯片&#xff08;SoC芯片&am…

Python-主线程控制子线程-3

需求&#xff1a;在Python-主线程控制子线程结束-2的基础上&#xff0c;添加在子线程中执行操作并获取结果的功能。 一种常见的方法是使用队列&#xff08;Queue&#xff09;或者共享变量&#xff0c;在子线程中存储结果&#xff0c;然后在主线程中获取这些结果。这种方法可以…

联想小新Pro 16笔记本键盘失灵处理方法

问题描述&#xff1a; 联想小新Pro 16新笔记本开机准备激活&#xff0c;到连接网络的时候就开始触控板、键盘失灵&#xff0c;但是有意思的是键盘的背光灯是可以调节关闭的&#xff1b;外接鼠标是正常可以移动的&#xff0c;但是只要拔掉外接鼠标再插回去的时候就不能用了&…