逸学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);
        //逐一处理(遍历)里面是lambda
        list.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.0
        ArrayList<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流是方便操作集合/数组的手段,集合/数组才是开发中的目的。

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

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

相关文章

【MATLAB源码-第85期】基于farrow结构的滤波器仿真,截止频率等参数可调。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 Farrow结构是一种用于实现可变数字滤波器的方法&#xff0c;尤其适用于数字信号处理中的采样率转换和时变滤波。它通过多项式近似来实现对滤波器系数的平滑变化&#xff0c;使得滤波器具有可变的群延时或其他参数。 Farrow结…

AR道具特效制作工具

AR&#xff08;增强现实&#xff09;技术已经逐渐渗透到各个行业&#xff0c;为企业带来了全新的营销方式和用户体验。在这个背景下&#xff0c;美摄科技凭借其强大的技术实力和创新精神&#xff0c;推出了一款专为企业打造的美摄AR特效制作工具&#xff0c;旨在帮助企业轻松实…

8年老鸟整理,自动化测试-准备测试数据详细...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 大部分类型的测试…

陪玩圈子系统APP小程序H5,详细介绍,源码交付,支持二开!

陪玩圈子系统&#xff0c;页面展示&#xff0c;源码交付&#xff0c;支持二开&#xff01; 陪玩后端下载地址&#xff1a;电竞开黑陪玩系统小程序&#xff0c;APP&#xff0c;H5: 本系统是集齐开黑&#xff0c;陪玩&#xff0c;陪聊于一体的专业APP&#xff0c;小程序&#xff…

黑马React18: ReactRouter

黑马React: ReactRouter Date: November 21, 2023 Sum: React路由基础、路由导航、导航传参、嵌套路由配置 路由快速上手 1. 什么是前端路由 一个路径 path 对应一个组件 component 当我们在浏览器中访问一个 path 的时候&#xff0c;path 对应的组件会在页面中进行渲染 2. …

服务器主机安全的重要性及防护策略

在数字化时代&#xff0c;服务器主机安全是任何组织都必须高度重视的问题。无论是大型企业还是小型企业&#xff0c;无论是政府机构还是个人用户&#xff0c;都需要确保其服务器主机的安全&#xff0c;以防止数据泄露、网络攻击和系统瘫痪等严重后果。 一、服务器主机安全的重…

帝国cms开发一个泛知识类的小程序的历程记录

#帝国cms小程序# 要开发一个泛知识类的小程序&#xff0c;要解决以下几个问题。 1。知识内容的分类。 2。知识内容的内容展示。 3。知识内容的价格设置。 4。用户体系&#xff0c;为简化用户的操作&#xff0c;在用户进行下载的时候&#xff0c;请用户输入手机号&#xff…

AI:86-基于深度学习的街景图像地理位置识别

🚀 本文选自专栏:人工智能领域200例教程专栏 从基础到实践,深入学习。无论你是初学者还是经验丰富的老手,对于本专栏案例和项目实践都有参考学习意义。 ✨✨✨ 每一个案例都附带有在本地跑过的代码,详细讲解供大家学习,希望可以帮到大家。欢迎订阅支持,正在不断更新中,…

鸿蒙4.0开发笔记之DevEco Studio页面操作router的pushUrl页面跳转与back返回上一页(五)

一、认识组件 关于HarmonyOS中ArkTS的基础组件请参见文章鸿蒙4.0开发笔记之ArkTs语言基础与基本组件结构&#xff08;四&#xff09; 二、实现页面跳转pushUrl 1、操作说明 实现页面跳转的核心便是router.pushUrl的调用&#xff0c;操作起来也很简单&#xff0c;总共就四步…

微机原理_1

一、单项选择题(本大题共15小题,每小题3分,共45分。在每小题给出的四个备选项中,选出一个正确的答案,请将选定的答案填涂在答题纸的相应位置上。) 1,下列8086CPU标志寄存器的标志位中,不属于状态标志位的是(&#xff09; A. OF B. IF C. AF D. PF 8086微处理器可寻址访问的最大…

Ps:裁剪工具 - 裁剪预设的应用

裁剪工具提供了两种类型的裁剪方式。 一种是仅按宽高比&#xff08;比例&#xff09;进行裁剪&#xff0c;常在对图像进行二次构图时采用。 另一种则按指定的图像尺寸&#xff08;宽度值和高度值&#xff09;及分辨率&#xff08;宽 x 高 x 分辨率&#xff09;进行裁剪。其实质…

Sentinel 监控数据持久化(mysql)

Sentinel 实时监控仅存储 5 分钟以内的数据&#xff0c;如果需要持久化&#xff0c;需要通过调用实时监控接口来定制&#xff0c;即自行扩展实现 MetricsRepository 接口&#xff08;修改 控制台源码&#xff09;。 本文通过使用Mysql持久化监控数据。 1.构建存储表&#xff08…

leetcode:520. 检测大写字母

一、题目&#xff1a; 链接&#xff1a;520. 检测大写字母 - 力扣&#xff08;LeetCode&#xff09; 函数原型&#xff1a;bool detectCapitalUse(char* word) 二、思路&#xff1a; 本题较为简单&#xff0c;分为三种情况&#xff1a; 1.首字母大写&#xff0c;其余小写 2.首字…

Github Copilot AI编码完成工具

目录 一、GitHub Copilot 1、简介 2、工作原理 3、功能 二、GitHub Copilot X 1、什么是 GitHub Copilot X 2、GitHub Copilot X 的功能 三、支持、使用 1、支持 2、使用 四、实际研究、验证(代码方向) 1、代码生成 2、代码提示 3、生成测试用例 4、代码解释 5…

【Axure高保真原型】树形表格

今天和大家分享树形表格的原型模板&#xff0c;点击树的箭头可以打开或者收起子节点&#xff0c;点击表格内容&#xff0c;可以选中该行内容实现高亮变色效果&#xff0c;树形表格是通过中继器制作的&#xff0c;使用简单&#xff0c;只需要按要求填写中继器表格即可&#xff0…

深度学习常见激活函数:ReLU,sigmoid,Tanh,softmax,Leaky ReLU,PReLU,ELU整理集合,应用场景选择

文章目录 1、ReLU 函数&#xff08;隐藏层中是一个常用的默认选择&#xff09;1.1 优点1.2 缺点 2、sigmoid 函数2.1 优点2.2 缺点 3、Tanh 函数3.1 优点3.2 缺点 4、softmax 函数&#xff08;多分类任务最后一层都会使用&#xff09;5、Leaky ReLU 函数5.1 优点5.2 缺点 6、PR…

2023.11.22 -数据仓库的概念和发展

目录 https://blog.csdn.net/m0_49956154/article/details/134320307?spm1001.2014.3001.5501 1经典传统数仓架构 2离线大数据数仓架构 3数据仓库三层 数据运营层,源数据层&#xff08;ODS&#xff09;&#xff08;Operational Data Store&#xff09; 数据仓库层&#…

【深度学习】不用Conda在PP飞桨Al Studio三个步骤安装永久PyTorch环境

在 PaddlePaddle AI Studio 中使用 Python 虚拟环境安装 PyTorch 免责声明 在阅读和实践本文提供的内容之前&#xff0c;请注意以下免责声明&#xff1a; 侵权问题: 本文提供的信息仅供学习参考&#xff0c;不用做任何商业用途&#xff0c;如造成侵权&#xff0c;请私信我&am…

基于SSM的济南旅游网站设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…

数字逻辑电路基础-时序逻辑电路之锁存器

文章目录 一、锁存器简介二、verilog源码三、综合及仿真结果 一、锁存器简介 本文介绍数字逻辑电路中一种常用的基础时序逻辑电路-锁存&#xff0c;顾名思义&#xff0c;它的功能就是将输入在控制信号有效时透明传输到输出端&#xff0c;当控制信号无效时&#xff0c;输出值保…