当前位置: 首页 > news >正文

逸学java【初级菜鸟篇】9.3 Stream流

hi,我是逸尘,一起学java吧


得益于Lambda所带来的函数式编程,引入了一个全新的Stream流概念(就是都基本使用lambda的形式)。

流处理

我们首先理解什么是流处理,它类似于sql语句,可以执行非常复杂的过滤,映射,查找,收集等功能,且代码很少,但是可读性不高。字如其名,它的处理如同流淌的水一样,或者可以理解为流水线一样。

Stream流

Stream流也是流处理的一种,大多数流处理都是在Stream接口处理的,它是一个泛接口,所以它可以操作的元素是任意对象,他的操作可以用lambda去书写(推荐)。

生成Stream流

Stream操作集合和数组的第一步是得到(生成)Stream流。

在Collection接口默认方法是stream()生成流。

 在数组中使用Arrays.stream(数组) /或Stream.of(数组);

 中间操作方法

其次我们就可以使用中间操作来处理这些元素对象。

这里举出一些常见的API

  • forEach : 逐一处理(遍历)
  • count:统计个数
  • filter : 过滤元素 【数据过滤】
  • distinct:去除重复元素 【数据过滤】
  • limit : 取前几个元素 【数据过滤】
  • skip : 跳过前几个 【数据过滤】
  • map : 加工方法 【数据映射】
  • allMatch:判断流中的元素是否会全部符合某一个条件 【数据查找】
  • concat:合并流

终结操作方法

终结操作方法调用以后流就无法使用了它是流的最后一个过程。

常见的有API有

单独保存的操作方法

  • collect() 方法配合collectors类将流的结果进行保存

处了stream流本身的方法我们还有两个可以协助流操作的类

Collectors类

collectors是一个收集器类,可以将Stream流对象进行封装,归集,分组,是数据的收集,筛选出特殊的数据,可以复杂的统计。

1.toList()将流元素封装到List集合 toSet() toMap()类似

2.toCollection(Supplier<C> collectionFactory) 将流中的元素收集到指定类型的集合中的方法

即一个类型为 Supplier<C> 的函数式接口,其中 C 是要创建的集合类型。例如,如果我们想要创建一个 LinkedList 集合,可以这样使用该方法: 

List<Integer> list = Stream.of(1, 2, 3, 4, 5).collect(Collectors.toCollection(LinkedList::new));

3.groupingBy(Function<? super T, ? extends K> classifier) 

  • 一个函数式接口 classifier,表示如何对流中的元素进行分类。

例如,我们有一个字符串列表,并希望按照字符串长度分组:

List<String> list = Arrays.asList("apple", "banana", "peach", "grape","pear");
Map<Integer, List<String>> map = list.stream().collect(Collectors.groupingBy(String::length));

 在上面的代码中,我们使用 String::length 函数式接口将字符串转换为它的长度,并将其作为分类键。运行结果如下:

{4=[pear], 5=[apple, peach,grape], 6=[banana]}

需要注意的是,groupingBy() 方法返回的是一个 Map 对象,其中键是分类键.

Collectors.groupingBy() 方法还提供了第二个参数 downstream,用于进一步对分组的结果进行处理。例如,我们可以使用 Collectors.counting() 方法统计每个分组中元素的数量:

Map<Integer, Long> map = list.stream().collect(Collectors.groupingBy(String::length, Collectors.counting()));

上面的代码中,我们使用 Collectors.counting() 方法作为 downstream 参数,统计了每个分组中元素的数量,并将结果封装为 Long 类型。运行结果如下:

{4=1, 5=3, 6=1}

4.toConcurrentMap

将流中的元素收集到一个并发 Map 中的方法

ConcurrentMap<Integer, String> concurrentMap = Stream.of("a", "b", "c").collect(Collectors.toConcurrentMap(String::length,Function.identity()));

在上面的例子中,我们使用 toConcurrentMap() 方法创建了一个并发 Map,它将字符串的长度作为键,字符串本身作为值。具体来说,这个方法接受两个参数:

一个函数式接口 keyMapper,表示如何将流中的元素转换成键;
一个函数式接口 valueMapper,表示如何将流中的元素转换成值。
对于上述例子中的流,String::length 函数式接口将字符串转换成它的长度,而 Function.identity() 函数式接口则将字符串映射成它本身。因此得到的结果为:

{1=a, 2=b, 3=c}

 5.以及averagingDouble计算元素平均值,maxBy返回符合条件的最大值,joining()按顺序将元素连接成一个String类型数据,counting()统计个数等等

optional类

这是一个容器类

它的主要功能是针对NullpointerException空指针异常做处理,可以保证保存的值不为null。

of()返回一个value值等于参数的optional实例

ofNullable()是返回一个value值等于非null参数的optional实例

filter()是给定条件值匹配

empty()是静态方法,返回一个空值的optional实例

案例 

我们上面的中间操作,其实是对我们的数据源进行加工。

这里我们简单做了一个去重        

package com.yd.yc;import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;public class Thirteen {public static void main(String[] args) {List<Integer> list = Arrays.asList(6,88,4,5,22,22,6,66,7);//原数据printeach(list);//获取stream,去重,收集器类重新封装List<Integer> collect = list.stream().distinct().collect(Collectors.toList());printeach(collect);}//遍历方法private static void printeach(List<Integer> list) {System.out.println("集合内容"+list);//逐一处理(遍历)里面是lambdalist.stream().forEach(n-> System.out.println(n+""));}
}

某个公司的部门,分为开财务部门和开发部门,现在需要进行月中数据结算。

创建一张员工

部门姓名年龄月工资性别
开发部张三2815000
开发部李四3520000
开发部王五2918000
财务部赵六3316000
财务部刘七3017000
财务部陈八2714000

对应的是我们的员工实体类

public class Employee {  private String name;  private int age;  private double monthlySalary;  private String gender;  private String department;  public Employee(String name, int age, double monthlySalary, String gender, String department) {  this.name = name;  this.age = age;  this.monthlySalary = monthlySalary;  this.gender = gender;  this.department = department;  }  public String getName() {  return name;  }  public int getAge() {  return age;  }  public double getMonthlySalary() {  return monthlySalary;  }  public String getGender() {  return gender;  }  public String getDepartment() {  return department;  }  
}

分别筛选出2个部门的最高工资的员工信息,封装成优秀员工对象topperformer

方案A

package com.yd.yc;import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;public class EmployeeTest {public static void main(String[] args) {Employee employee1 = new Employee("张三", 28, 15000, "男", "开发部");Employee employee2 = new Employee("李四", 35, 20000, "女", "开发部");Employee employee3 = new Employee("王五", 29, 18000, "男", "开发部");Employee employee4 = new Employee("赵六", 33, 16000, "女", "财务部");Employee employee5 = new Employee("刘七", 30, 17000, "男", "财务部");Employee employee6 = new Employee("陈八", 27, 44000, "女", "财务部");//测试//System.out.println(employee1.getName());  // 输出:张三//System.out.println(employee2.getMonthlySalary());  // 输出:20000.0ArrayList<Employee> employeeList = new ArrayList<>();employeeList.add(employee1);employeeList.add(employee2);employeeList.add(employee3);employeeList.add(employee4);employeeList.add(employee5);employeeList.add(employee6);//A方案//filter是过滤找到符合条件的元素//Collectors.maxBy去返回符合条件的最大值,Comparator.comparing(param),param : 这个参数是Function函数式对象,默认大,Comparator.reverseOrder()默认倒序Optional<Employee> result = employeeList.stream().filter(e -> "开发部".equals(e.getDepartment())).collect(Collectors.maxBy(Comparator.comparing(Employee::getMonthlySalary)));//返回一个实体类对象Employee employee = result.get();System.out.println(employee.getName());//第二种写法Employee  resultOne= employeeList.stream().filter(e -> "财务部".equals(e.getDepartment())).max((o1, o2) -> Double.compare(o1.getMonthlySalary(), o2.getMonthlySalary())).get();//必须重写toString才可以有内容System.out.println(resultOne);System.out.println(resultOne.getMonthlySalary());//包装在一个优秀员工里List<Employee> topEmployees = new ArrayList<>();topEmployees.add(resultOne);topEmployees.add(employee);System.out.println(topEmployees);}
}

 方案B

        //B方案Map<String, List<Employee>> groupedByDepartment = employeeList.stream()//分组.collect(Collectors.groupingBy(Employee::getDepartment));List<Employee> topEmployees = new ArrayList<>();for (List<Employee> departmentEmployees : groupedByDepartment.values()) {Employee topEmployee = departmentEmployees.stream().max(Comparator.comparingDouble(Employee::getMonthlySalary))//注意,如果一个部门没有员工,那么这个方法将返回null//该方法在给定的流中找不到元素时返回一个默认值。.orElse(null);if (topEmployee != null) {topEmployees.add(topEmployee);}}System.out.println(topEmployees);

我们要注意的是stream流是方便操作集合/数组的手段,集合/数组才是开发中的目的。

相关文章:

逸学java【初级菜鸟篇】9.3 Stream流

hi&#xff0c;我是逸尘&#xff0c;一起学java吧 得益于Lambda所带来的函数式编程&#xff0c;引入了一个全新的Stream流概念&#xff08;就是都基本使用lambda的形式&#xff09;。 流处理 我们首先理解什么是流处理&#xff0c;它类似于sql语句&#xff0c;可以执行非常复…...

html页面直接使用elementui Plus时间线 + vue3

直接上效果图 案例源码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title><script src"../js/vue3.3.8/vue.global.js"></script><link rel"styles…...

信息压缩模型在自然语言处理中的应用和探讨

信息压缩模型在自然语言处理中的应用和探讨 摘要:正文:结论:附录:摘要: 随着人工智能和深度学习的发展,自然语言处理(NLP)在信息处理中的角色变得越来越重要。然而,海量的自然语言数据为信息处理带来了挑战——更多的信息通常意味着更高的处理成本,并可能导致效率降低。为…...

新版mmdetection3d将3D bbox绘制到图像

环境信息 使用 python mmdet3d/utils/collect_env.py收集环境信息 sys.platform: linux Python: 3.7.12 | packaged by conda-forge | (default, Oct 26 2021, 06:08:21) [GCC 9.4.0] CUDA available: True numpy_random_seed: 2147483648 GPU 0,1: NVIDIA GeForce RTX 3090 …...

合伙人注册即得/创业平台扶持!

问心一语持续体验中~ 与公司签订线下&#xff08;线上&#xff09;纸质合伙人代理合同&#xff0c;具备法律效力。 一级直推、非一级直推注册即得奖励。(消耗完毕被邀请用户赠送的AI免费使用条数) 即&#xff1a;邀请1人注册即得并消耗&#xff01;只需注册无需充值&#xff…...

02_使用API_String

StringBuilder StringBuilder 代表可变字符串对象&#xff0c;相对于是一个容器&#xff0c;它里面装的字符串是可以改变的&#xff0c;就是用来操作字符串的好处&#xff1a;StringBuilder 比 String 更适合做字符串的修改操作&#xff0c;效率会更高&#xff0c;代码也会更简…...

Spring IOC/DI和MVC及若依对应介绍

文章目录 一、Spring IOC、DI注解1.介绍2.使用 二、Spring MVC注解1.介绍2.使用 一、Spring IOC、DI注解 1.介绍 什么是Spring IOC/DI&#xff1f; IOC(Inversion of Control&#xff1a;控制反转)是面向对象编程中的一种设计原则。其中最常见的方式叫做依赖注入&#xff08;…...

python的多层嵌套循环时,break可以退出多层循环吗?

在Python中&#xff0c;break 语句只能退出当前所在的循环&#xff0c;无法直接退出多层嵌套的循环。但是&#xff0c;你可以通过使用一个标志变量或者通过使用异常来模拟退出多层循环的效果。 使用标志变量&#xff1a; flag False for i in range(5):for j in range(5):if…...

链表OJ--上

文章目录 前言一、反转链表二、移除链表元素三、链表中倒数第K个结点四、相交链表五、链表的中间结点 前言 一、反转链表 力扣206&#xff1a;反转链表- - -点击此处传送 思路图&#xff1a; 方法一&#xff1a;改变指向 方法二&#xff1a; 代码&#xff1a; //方法一 /…...

内衣洗衣机哪些品牌质量好实惠?小型洗衣机全自动

现在洗内衣内裤也是一件较麻烦的事情了&#xff0c;在清洗过程中还要用热水杀菌&#xff0c;还要确保洗衣液是否有冲洗干净&#xff0c;还要防止细菌的滋生等等&#xff0c;所以入手一款小型的烘洗全套的内衣洗衣机是非常有必要的&#xff0c;专门的内衣洗衣机可以最大程度减少…...

推荐一款适合做智慧旅游的前端模板

目录 前言 一、功能介绍 二、前端技术介绍 三、功能及界面设计介绍 1、数据概览 2、车辆监控 3、地图界面 4、其它功能 四、扩展说明 总结 前言 智慧旅游是一种全新的旅游业务模式&#xff0c;它充分利用先进的信息技术&#xff0c;提升旅游体验&#xff0c;优化旅游管…...

VL06O报表添加增强字段

业务描述 用户需要在VL06O事务代码下进行批量交货过账&#xff0c;现有的筛选条件不太适用当前公司的业务&#xff0c;需要在报表中新增三个交货单增强字段&#xff0c;方便其筛选&#xff08;选择屏幕没有加&#xff0c;用户在报表里用标准按钮功能自己筛选&#xff09; 效果…...

SpringBoot Admin

前言 Spring Boot Admin 是一个管理和监控 Spring Boot 应用程序的开源项目&#xff0c;它提供了一个简洁的 Web 界面来监控 Spring Boot 应用程序的状态和各种运行时指标。Spring Boot Admin 可以帮助开发者快速了解应用程序的状态&#xff0c;并快速定位错误或性能问题。下面…...

Java基础-----正则表达式

文章目录 1.简介2.目的3.学习网站4.常用匹配字符5.String类中用到正则表达式的方法 1.简介 又叫做规则表达式。是一种文本模式&#xff0c;包括普通字符和特殊字符&#xff08;元字符&#xff09;。正则使用单个字符来描述、匹配一系列某个句法规则的字符串&#xff0c;通常用…...

基于 Eureka 的 Ribbon 负载均衡实现原理【SpringCloud 源码分析】

目录 一、前言 二、源码分析 三、负载均衡策略 一、前言 如下图&#xff0c;我们在 orderserver 中通过 restTemplate 向 usersever 发起 http 请求&#xff0c;在服务拉取的时候&#xff0c;主机名 localhost 是用服务名 userserver 代替的&#xff0c;那么该 url 是一个可…...

如何用CHAT解释文章含义?

问CHAT&#xff1a;解释“ 本身乐善好施&#xff0c;令名远近共钦&#xff0c;待等二十左右&#xff0c;定有高亲可攀&#xff1b;而且四德俱备&#xff0c;帮夫之缘亦有。主持家事不紊&#xff0c;上下亦无闲言。但四十交进&#xff0c;家内谨防口舌&#xff0c;须安家堂&…...

创作4周年

&#x1f64c;秋名山码民的主页 &#x1f602;oi退役选手&#xff0c;Java、大数据、单片机、IoT均有所涉猎&#xff0c;热爱技术&#xff0c;技术无罪 &#x1f389;欢迎关注&#x1f50e;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; 获取源码&#xff0c;添加WX 目录 前言机…...

《opencv实用探索·一》QT+opencv实现图片拼接和Mat转QImage

本文利用opencv实现了几个好用的功能&#xff0c;包含两个文件&#xff0c;如下&#xff1a; 源码放在文章末尾 imageProcessing类包含三个功能&#xff1a; 1、图像拼接 cv::Mat imageMosaic(cv::Mat mat1, cv::Mat mat2, MosaicMode mosaicMode);mat1和mat2为两个待拼接的…...

Apahce虚拟主机配置演示

在企业的真实环境中&#xff0c;一台WEB服务器发布单个网站会非常浪费资源&#xff0c;所以一台WEB服务器一般都会发布多个网站&#xff0c;少则3-5个&#xff0c;多个10-20个网站。在一台服务器上发布多网站&#xff0c;也称之为部署多个虚拟主机。 WEB虚拟机主机配置方法主要…...

加班做报表被嘲低效!快用大数据分析工具

做数据分析报表很耗时间&#xff0c;因为不仅要解决多业务系统数据质量标准不一问题&#xff0c;还需要进行大量的公式计算、报表设计与制作。但那是以前&#xff0c;在大数据分析工具强势崛起的当下&#xff0c;这些工作都能交给大数据分析工具来做了。以前是花90%的时间做报表…...

SlickGPT:专为开发者设计的轻量级AI助手工具链

1. 项目概述&#xff1a;一个为开发者打造的“智能副驾”最近在GitHub上看到一个挺有意思的项目&#xff0c;叫slickgpt。初看这个名字&#xff0c;你可能会觉得这又是一个基于GPT API的简单封装&#xff0c;或者是一个聊天界面。但如果你点进去&#xff0c;仔细看看它的README…...

超越DOA估计:原子范数最小化在Matlab中的三种创新应用场景

原子范数最小化在Matlab中的三大前沿应用实践 原子范数最小化&#xff08;Atomic Norm Minimization, ANM&#xff09;作为压缩感知领域的重要工具&#xff0c;早已超越了传统的波达方向&#xff08;DOA&#xff09;估计范畴。本文将带您探索ANM在频谱感知、机械故障诊断和图像…...

科罗拉多州撤销维修保护法案未通过,多方倡导助力维修权保障

颇具争议法案&#xff1a;撤销维修保护措施的尝试 科罗拉多州一项颇具争议的法案未能通过&#xff0c;该法案原本旨在撤销该州的一些维修保护措施。这项法案一直是维修权倡导者的针对目标&#xff0c;他们将其视为科技公司试图在美国更广泛地推翻维修立法的一个风向标。 2024年…...

BilldDesk终极指南:为什么这款免费远程桌面软件正在改变游戏规则?

BilldDesk终极指南&#xff1a;为什么这款免费远程桌面软件正在改变游戏规则&#xff1f; 【免费下载链接】billd-desk 基于Vue3 WebRTC Nodejs Flutter搭建的远程桌面控制、游戏串流 项目地址: https://gitcode.com/gh_mirrors/bi/billd-desk BilldDesk是一款基于现…...

全新AOD409 P沟道功率MOSFET晶体管——AOS(美国万代) 集成电路IC 芯片

AOD409 是AOS&#xff08;Alpha & Omega Semiconductors&#xff0c;美国万代半导体&#xff09;推出的P沟道功率MOSFET。它基于AOS先进的沟槽MOSFET工艺技术&#xff0c;在紧凑的DPAK&#xff08;TO-252&#xff09;表面贴装封装内&#xff0c;集成了60V的漏源击穿电压和-…...

COMTool串口调试助手:从新手到专家的5个实战技巧

COMTool串口调试助手&#xff1a;从新手到专家的5个实战技巧 【免费下载链接】COMTool Cross platform communicate assistant(Serial/network/terminal tool)&#xff08; 跨平台 串口调试助手 网络调试助手 终端工具 linux windows mac Raspberry Pi &#xff09;支持插件和二…...

Xshell评估过期后,别急着重装!先试试这个注册表修复大法(附Win10/11通用步骤)

Xshell评估过期后的终极修复指南&#xff1a;深入解析注册表空间限制问题 当你看到"Xshell评估期已过"的提示时&#xff0c;第一反应可能是卸载重装。但如果你遇到了"The feature you are trying to use is on a network resource that is unavailable"这样…...

别再只会用SUM了!Excel多表汇总和跨列求和,用SUMIF(S)函数一键搞定

告别低效统计&#xff1a;用SUMIF(S)函数实现Excel高阶数据汇总 财务部的张琳最近遇到了一个头疼的问题——领导要求她汇总全年12个月的销售数据&#xff0c;并分别统计各区域"计划"与"实际"销售额的完成情况。面对电脑里密密麻麻的Excel文件&#xff0c;她…...

FreeRTOS Demo里的Check任务与流缓冲区:新手容易忽略的稳定性设计与优化技巧

FreeRTOS Demo里的Check任务与流缓冲区&#xff1a;新手容易忽略的稳定性设计与优化技巧 在嵌入式开发中&#xff0c;FreeRTOS作为一款轻量级实时操作系统&#xff0c;其官方Demo工程往往蕴含着许多值得深入挖掘的设计智慧。很多开发者在学习FreeRTOS时&#xff0c;会重点关注任…...

LSTM在时序预测中的核心原理与工业实践

1. 长短期记忆网络在序列预测中的核心价值 长短期记忆网络&#xff08;LSTM&#xff09;作为循环神经网络的特殊变体&#xff0c;在时间序列预测领域已经证明了其独特优势。与传统RNN相比&#xff0c;LSTM通过精心设计的门控机制&#xff0c;有效解决了长期依赖问题。我在多个工…...