【Java】常用Stream API

常见 Stream 流表达式

总体结构图

在这里插入图片描述

一、两大类型

中间操作(Intermediate Operations)

中间操作是指在Stream上执行的操作, 它们返回一个新的Stream, 允许你链式地进行多个中间操作.

终端操作(Terminal Operations)

对Stream进行最终处理的操作, 当调用终端操作时, Stream会开始执行中间操作, 并生成最终的结果或副作用.终端操作是Stream的"触发器", 一旦调用终端操作, Stream就不能再被使用, 也不能再进行中间操作.

二、中间操作

2.1 filter

用于根据指定条件过滤元素.它接收一个条件作为参数, 只保留满足条件的元素, 并生成一个新的Stream.

在这里插入图片描述

示例

    /** TODO **************************************  filter **************************************  */
    
    public static void filter() {
        List<String> tempList = Arrays.asList("小芳", "小李", "小林", "小王");
        List<String> resList = tempList.stream()
                .filter(s -> s.contains("王"))
                .collect(Collectors.toList());
        System.out.println(resList.toString());
    }

输出结果

[小王]

2.2 map

用于对每个元素执行映射操作, 将元素转换成另一种类型.它接收一个Function(映射函数)作为参数, 对每个元素应用该映射函数, 并生成一个新的Stream.

在这里插入图片描述

示例

 /** TODO **************************************  map **************************************  */
    
    public static void map() {
        List<String> tempList = Arrays.asList("小芳", "小李", "小林", "小王");
        List<String> resList = tempList.stream()
        .map(s -> "姓名: " + s)
        .collect(Collectors.toList());
        System.out.println(resList.toString());
    }

输出结果

  [姓名: 小芳, 姓名: 小李, 姓名: 小林, 姓名: 小王]

2.3 flatMap

类似于map操作,但是 flatMap 操作可以将每个元素映射成一个 Stream,然后把所有生成的 Stream 合并成一个新的Stream。

在这里插入图片描述

示例

新建一个静态内部类, 然后聚合类中的集合数据

@Data
static class Personnel {
    // 人员姓名
    private String name;
    // 人员标签
    private List<String> tagList;

    public Personnel(String name, List<String> tagList) {
        this.name = name;
        this.tagList = tagList;
    }
}

Tips: 就现在想要把 List 中的 tagList 聚合后进行处理, 代码如下:

public static void main(String[] args) {
    Personnel personA = new Personnel("张三", Arrays.asList("抽烟", "喝酒", "烫头"));
    Personnel personB = new Personnel("李斯", Arrays.asList("编码", "喝酒", "踢足球"));
    List<Personnel> personnelList = Arrays.asList(personA, personB);
    personnelList.stream()
            .flatMap(p -> p.getTagList().stream())
            .forEach(s -> System.out.print(s + " "));
}

输出结果

抽烟 喝酒 烫头 编码 喝酒 踢足球

2.4 sorted

用于对Stream中的元素进行排序,默认按照自然顺序进行排序。也可以传入自定义的Comparator来指定排序规则。

  /** TODO **************************************  sorted **************************************  */

    public static void sorted() {
        List<Integer> numList = Arrays.asList(10, 20, 18, 300, 30, 2);
        // ① 默认排序
        List<Integer> orderList = numList.stream()
                .sorted()
                .collect(Collectors.toList());
        System.out.printf("① 默认排序: %s%n", orderList);
        // ② 自定义排序
        List<Integer> orderDescList = numList.stream()
                .sorted((x, y) -> {
                    return y.compareTo(x);
                })
                .collect(Collectors.toList());
        System.out.printf("② 自定义排序: %s%n", orderDescList);
    }

输出结果

① 默认排序: [2, 10, 18, 20, 30, 300]
② 自定义排序: [300, 30, 20, 18, 10, 2]

2.5 distinct

用于去除 Stream 中重复的元素,确保最终的 Stream 中每个元素都是唯一的。

示例

   /** TODO **************************************  distinct **************************************  */

    public static void distinct() {
        List<Integer> numList = Arrays.asList(1,1,1,1,2,3,2,2);
        List<Integer> distinctList = numList.stream()
                .distinct()
                .collect(Collectors.toList());
        System.out.println(distinctList);
    }

输出结果

[1, 2, 3]

2.6 limit

用于限制Stream的大小,返回一个最大包含前n个元素的新Stream。

示例

 /** TODO **************************************  limit **************************************  */
    
    public static void limit(){
        List<Integer> numList = Arrays.asList(1,2,3,4,5,6,7,8);
        List<Integer> limitList = numList.stream()
                .limit(4)
                .collect(Collectors.toList());
        System.out.println(limitList);
    }

输出结果

[1, 2, 3, 4]

2.7 skip

用于跳过Stream中的前n个元素,返回一个丢弃了前n个元素后剩余元素的新Stream。

示例

    /** TODO **************************************  skip **************************************  */

    public static void skip(){
        List<Integer> numList = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8);
        List<Integer> skipList = numList.stream()
                .skip(numList.size() - 2)
                .collect(Collectors.toList());
        System.out.println(skipList);
    }

输出结果

[7, 8]

2.8 peek

用于对每个元素执行一个操作,同时保持Stream的流。它可以用于调试或记录Stream中的元素。

示例

  /** TODO **************************************  peek **************************************  */

    public static void peek(){
        List<Integer> numList = Arrays.asList(5, 6, 7, 8);
        List<Integer> resList = numList.stream()
                .peek(System.out::println)
                .filter(s -> s == 5)
                .peek(s -> System.out.printf("过滤后的:%d%n", s))
                .collect(Collectors.toList());
    }

输出结果

5
过滤后的:5
6
7
8

三、终端操作

在Java Stream API中,终端操作(Terminal Operations)是对Stream进行最终处理的操作。
当调用终端操作时,Stream会开始执行中间操作,并生成最终的结果或副作用。
终端操作是Stream的触发器,一旦调用终端操作,Stream就不能再被使用,也不能再进行中间操作。

3.1 forEach

对Stream中的每个元素执行指定的操作,接收一个Consumer(消费者函数)作为参数。它通常用于对Stream中的元素进行输出或执行某些操作,但不会返回任何结果。

示例

  /** TODO **************************************  forEach **************************************  */

    public static void forEach(){
        // 给公司工资普涨 500
        List<Integer> salaryList = Arrays.asList(12000, 20000, 30000, 4000);
        salaryList.stream()
                .peek(s -> System.out.print("工资普涨前:" + s))
                .map(s -> s + 500)
                .forEach(s -> {
                    System.out.println("--工资普涨后:" + s);
                });
    }

输出结果

工资普涨前:12000--工资普涨后:12500
工资普涨前:20000--工资普涨后:20500
工资普涨前:30000--工资普涨后:30500
工资普涨前:4000--工资普涨后:4500

3.2 collect

用于将Stream中的元素收集到一个容器中,接收一个Collector(收集器)作为参数。
它允许你在Stream中执行各种集合操作,例如将元素收集到List、Set、Map等容器中。

示例

把 User 实体集合转换为 Map 集合,名字作为 key,工资作为 Name

 /** TODO **************************************  collect **************************************  */

public static void collectTest(){

        List<User> userList = Arrays.asList(new User("张三", 2000.5),
        new User("李斯", 11000.5),
        new User("王二", 12000.5),
        new User("张六", 32000.5),
        new User("赵公子", 1000000.0));
        Map<String, Double> userSalaryMap = userList.stream()
        .collect(Collectors.toMap(User::getName, User::getSalary));
        userSalaryMap.forEach((k, v) -> {
        System.out.printf("姓名:%s,工资:%.2f%n", k, v);
        });
  }

@Data
@AllArgsConstructor
static class User {
    private String name;
    private Double salary;
}

输出结果

姓名:张三,工资:2000.50
姓名:赵公子,工资:1000000.00
姓名:张六,工资:32000.50
姓名:李斯,工资:11000.50
姓名:王二,工资:12000.50

3.3 toArray

将Stream中的元素转换成一个数组。返回一个包含所有元素的数组,返回的数组类型是根据流元素的类型自动推断的。如果流是空的,将返回一个长度为0的数组。

示例

  /** TODO **************************************  toArray **************************************  */

    public static void toArray(){
        // 示例整数流
        IntStream intStream = IntStream.of(1, 2, 3, 4, 5);
        // 使用toArray()将流中的元素收集到一个数组中
        int[] intArray = intStream.toArray();
        // 输出结果数组
        System.out.println(Arrays.toString(intArray));
        
    }

输出结果

[1, 2, 3, 4, 5]

3.4 reduce

Stream 类的 reduce() 方法是用于将流中的元素进行归约操作的方法。
接收一个 BinaryOperator(二元运算函数作为参数,用于对两个元素进行操作,并返回一个合并后的结果。
它可以将流中的所有元素按照指定的规则进行合并,并返回一个 Optional 对象,因为流可能为空。

示例

  /** TODO **************************************  reduce **************************************  */

    public static void reduceTest(){
        // 示例整数流
        IntStream intStream = IntStream.of(1, 2, 3, 4, 5);
        // 使用reduce()将流中的整数相加得到总和
        OptionalInt sumOptional = intStream.reduce((a, b) -> a + b);

        // 获取结果总和,如果流为空,则给出一个默认值0
        int sum = sumOptional.orElse(0);
        // 输出结果总和
        System.out.println("总和: " + sum);
    }

输出结果

总和: 15

3.5 min / max

Stream 类的 min() 和 max() 方法是用于查找流中的最小值和最大值的终端操作。它们接受一个 Comparator 对象作为参数来确定元素的顺序,并返回一个 Optional 对象,因为流可能为空。

示例

假设我们有一个包含整数的流,并且我们想找到其中的最小值和最大值

    /** TODO **************************************  min / max **************************************  */

    public static void minAndMaxTest(){
        // 示例整数流
        Stream<Integer> integerStream = Stream.of(1, 5, 3, 8, 2);

        // 使用min()找到最小值
        Optional<Integer> minOptional = integerStream.min(Integer::compareTo);
        if (minOptional.isPresent()) {
            System.out.println("最小值为: " + minOptional.get());
        } else {
            System.out.println("流为空.");
        }

        // 重新创建一个整数流,因为流已被消耗
        Stream<Integer> newIntegerStream = Stream.of(1, 5, 3, 8, 2);

        // 使用max()找到最大值
        Optional<Integer> maxOptional = newIntegerStream.max(Integer::compareTo);
        if (maxOptional.isPresent()) {
            System.out.println("最大值为: " + maxOptional.get());
        } else {
            System.out.println("流为空.");
        }
    }

输出结果

最小值为: 1
最大值为: 8

3.6 count

Stream 类的 count() 方法是用于计算流中元素个数的终端操作。它返回一个 long 类型的值,表示流中的元素数量。
count() 方法是一个终端操作,一旦调用该方法,流就被消耗,无法再次使用。

示例

   /** TODO **************************************  count **************************************  */

    public static void count() {
            List<Integer> numList = Arrays.asList(11, 22, 1, 2, 3, 4, 6, 33, 44, 553);
            long count = numList.stream().filter(s1 -> s1 > 10).count();
            System.out.println("大于10的个数数是:" + count);
    }

输出结果

大于10的个数数是:5

3.7 anyMatch / allMatch / noneMatch

Stream 类的 anyMatch(), allMatch(), 和 noneMatch() 是用于检查流中元素是否满足特定条件的终端操作。
它们返回一个布尔值,表示流中的元素是否满足指定的条件。这些方法在遇到满足条件的元素后可能会提前终止流的处理。

  • anyMatch检查是否有任意元素满足条件
  • allMatch检查是否所有元素都满足条件
  • noneMatch检查是否没有元素满足条件。

示例

  /**
     * TODO **************************************  anyMatch / allMatch / noneMatch **************************************
     */

    public static void matchTest() {
        // 示例整数流
        Stream<Integer> integerStream = Stream.of(1, 5, 3, 8, 2);

        // 使用anyMatch()检查是否存在元素大于5
        boolean anyGreaterThan5 = integerStream.anyMatch(num -> num > 4);
        System.out.println("是否存在元素大于 5 ?" + anyGreaterThan5);

        // 重新创建一个整数流,因为流已被消耗
        Stream<Integer> newIntegerStream = Stream.of(1, 5, 3, 8, 2);

        // 使用allMatch()检查是否所有元素都小于10
        boolean allLessThan10 = newIntegerStream.allMatch(num -> num < 10);
        System.out.println("所有元素都小于10 ? " + allLessThan10);

        // 重新创建一个整数流,因为流已被消耗
        Stream<Integer> newestIntegerStream = Stream.of(1, 5, 3, 8, 2);

        // 使用noneMatch()检查是否没有元素等于10
        boolean noneEqualTo10 = newestIntegerStream.noneMatch(num -> num == 10);
        System.out.println("是否没有元素等于 10 ? " + noneEqualTo10);
    }

输出结果

是否存在元素大于 5 ?true
所有元素都小于10 ? true
是否没有元素等于 10 ? true

3.8 findFirst / findAny

Stream 类的 findFirst() 和 findAny() 方法用于在流中查找元素的终端操作.

它们都返回一个 Optional 对象,表示找到的元素或元素的可能性。
在并行流中,findAny() 方法可能更快,因为它不一定要遍历所有元素。
在串行 Stream 中,findFirst()和 findAny() 返回的是相同的元素,
在并行Stream中,findAny()返回的是最先找到的元素。

示例

假设我们有一个包含整数的流,并且我们想查找其中的某个元素。

   /**
     * TODO **************************************  findFirst / findAny **************************************
     */

    public static void FindStreamTest () {
        // 示例整数流
        Stream<Integer> integerStream = Stream.of(1, 5, 3, 8, 2);

        // 使用findFirst()找到第一个元素
        Optional<Integer> firstElementOptional = integerStream.findFirst();
        if (firstElementOptional.isPresent()) {
            System.out.println("发现第一个元素: " + firstElementOptional.get());
        } else {
            System.out.println("流为空!");
        }

        // 重新创建一个整数流,因为流已被消耗
        Stream<Integer> newIntegerStream = Stream.of(1, 5, 3, 8, 2);

        // 使用findAny()找到任意一个元素
        Optional<Integer> anyElementOptional = newIntegerStream.findAny();
        if (anyElementOptional.isPresent()) {
            System.out.println("找到任意一个元素: " + anyElementOptional.get());
        } else {
            System.out.println("流为空!");
        }
    }

输出结果

发现第一个元素: 1
找到任意一个元素: 1

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

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

相关文章

[保研/考研机试] KY3 约数的个数 清华大学复试上机题 C++实现

题目链接&#xff1a; KY3 约数的个数 https://www.nowcoder.com/share/jump/437195121691716950188 描述 输入n个整数,依次输出每个数的约数的个数 输入描述&#xff1a; 输入的第一行为N&#xff0c;即数组的个数(N<1000) 接下来的1行包括N个整数&#xff0c;其中每个…

Python AI 绘画

Python AI 绘画 本文我们将为大家介绍如何基于一些开源的库来搭建一套自己的 AI 作图工具。 需要使用的开源库为 Stable Diffusion web UI&#xff0c;它是基于 Gradio 库的 Stable Diffusion 浏览器界面 Stable Diffusion web UI GitHub 地址&#xff1a;GitHub - AUTOMATI…

[HDLBIts] Exams/m2014 q4j

Implement the following circuit: ("FA" is a full adder) module top_module (input [3:0] x,input [3:0] y, output [4:0] sum);assign sumxy; endmodule

【Java多线程学习7】Java线程池技术

线程池技术 一、什么是线程池 线程池顾名思义是管理一组线程的池子。当有任务要处理时&#xff0c;直接从线程池中获取线程来处理&#xff0c;处理完之后线程不会立即销毁&#xff0c;而是等待下一个任务。 二、为什么要使用线程池? 线程池的作用&#xff1f; 1、降低资源…

性能测试—Jmeter工具

文章目录 性能测试1. 术语介绍2. 方法3. 应用场景4. 工具&#xff08;Jmeter&#xff09;4.1 介绍4.2 元件和组件4.2.2 元件4.2.1 组件 4.3 作用域4.4 参数化4.5 执行脚本 性能测试 1. 术语介绍 响应时间(Response time)&#xff1a;对请求作出响应所需要的时间。 在互联网上对…

Protues如何安装下载使用:STM32利用Protues进行仿真

文章目录&#xff1a; 一&#xff1a;Proteus仿真的使用步骤 第一步&#xff1a;Proteus新建项目 第二步&#xff1a;Proteus设计电路图&#xff08;选取元器件、摆放元器件、编辑元器件属性、原理图布线&#xff09; 第三步&#xff1a;程序代码编写 第四步&#xff1a;…

Docker源码阅读 - goland环境准备

docker 源码分为两部分 cli 和 moby&#xff08;docker&#xff09; tips: docker是从moby拷贝过去的&#xff1b;docker整体是一个C-S架构&#xff0c;cli客户端&#xff0c;docker服务端 docker-ce&#xff1a;https://github.com/docker/docker-ce cli&#xff1a;https://…

【Fegin技术专题】「原生态」打开Fegin之RPC技术的开端,你会使用原生态的Fegin吗?(上)

前提介绍 Feign是SpringCloud中服务消费端的调用框架&#xff0c;通常与ribbon&#xff0c;hystrix等组合使用。由于遗留原因&#xff0c;某些项目中&#xff0c;整个系统并不是SpringCloud项目&#xff0c;甚至不是Spring项目&#xff0c;而使用者关注的重点仅仅是简化http调…

Redis_分片集群

10. 分片集群 10.1简介 业务场景&#xff0c;需要存储50G的数据。对于内存和硬盘配置不足&#xff0c;选用两种方式 一种&#xff1a;纵向扩展&#xff1a;加内存&#xff0c;加硬盘&#xff0c;提高CPU。简单、直接。RDB存储效率要考虑。成本要考虑。二种&#xff1a;横向扩…

redis学习笔记(八)

文章目录 redis的配置redis的核心配置选项Redis的使用 redis的配置 cat /etc/redis/redis.confredis 安装成功以后,window下的配置文件保存在软件 安装目录下,如果是mac或者linux,则默认安装/etc/redis/redis.conf redis的核心配置选项 绑定ip&#xff1a;访问白名单&#x…

查看CentOS版本及系统位数与设置CentOS 7.9 2009 防火墙配置放开端口的命令与过程

一、查看CentOS版本及系统位数 1.1 命令汇总 //1、安装redhat-lsb yum install -y redhat-lsb//2、查看系统版本信息 lsb_release -a //3、查看系统位数 getconf LONG_BIT1.2 截图 二、设置CentOS7.9 2009 防火墙配置放开端口 2.1 命令汇总 //禁止防火墙开机启动。这种方法方…

Flink-串讲面试题

1. 概念 有状态的流式计算框架 可以处理源源不断的实时数据&#xff0c;数据以event为单位&#xff0c;就是一条数据。 2. 开发流程 先获取执行环境env&#xff0c;然后添加source数据源&#xff0c;转换成datastream&#xff0c;然后使用各种算子进行计算&#xff0c;使用s…

数据结构笔记--二叉树经典高频题

1--二叉树的最近公共祖先 主要思路&#xff1a; 最近祖先只有两种情况&#xff1a;① 自底向上&#xff0c;当两个目的结点分别在当前结点的左右子树时&#xff0c;当前结点为两个目的结点的最近祖先&#xff1b;② 最近祖先与其中一个目的结点相同&#xff0c;则另一个目的结点…

Linux命令200例:ls用于列出指定目录下的文件和子目录

&#x1f3c6;作者简介&#xff0c;黑夜开发者&#xff0c;全栈领域新星创作者✌。CSDN专家博主&#xff0c;阿里云社区专家博主&#xff0c;2023年6月csdn上海赛道top4。 &#x1f3c6;数年电商行业从业经验&#xff0c;历任核心研发工程师&#xff0c;项目技术负责人。 &…

android ndk clang交叉编译ffmpeg动态库踩坑

1.ffmpeg默认使用gcc编译&#xff0c;在android上无法使用&#xff0c;否则各种报错&#xff0c;所以要用ndk的clang编译 2.下载ffmpeg源码 修改configure文件&#xff0c;增加命令 cross_prefix_clang 修改以下命令 cc_default"${cross_prefix}${cc_default}" cxx…

selenium环境搭建

文章目录 1、下载谷歌浏览器2、下载谷歌驱动 1、下载谷歌浏览器 浏览器下载完成后&#xff0c;在任务管理器中禁止浏览器的自动更新。因为驱动版本必须和浏览器一致&#xff0c;如果浏览器更新了&#xff0c;驱动就用不起了。 2、下载谷歌驱动 谷歌驱动需要和谷歌浏览器版本…

AutoDL服务器的镜像版本太高,配置python3.7 tensorflow1.15版本的框架的步骤

1.选择一个实例&#xff0c;进入后端界面 2. 更新bashrc中的环境变量 conda init bash && source /root/.bashrc查看虚拟环境 conda info --envs可以看到此时有一个base的虚拟环境 但是它的python版本为3.8.10&#xff0c;无法安装tensorflow1.15,所以我们要创建一个…

Java实现对称加密(DES,AES)快速入门示例

对称加密是使用相同的密码进行加密和解密&#xff0c; 对称加密实现简单&#xff0c;安全性相比非对称加密较弱&#xff0c; 常用的对称加密算法有 DES&#xff0c;AES以及PDE等&#xff0c;关于对称加密相关概念参考&#xff1a; 对称加密、非对称加密深度解析 本篇介绍Java的…

模拟信号和数字信号的转换

此文章介绍的模拟信号与数字信号转换相关的知识有如下&#xff1a; 通信原理的PCM脉冲编码调制 数字电子技术的A/D与D/A 以及stm32的ADC与DAC 模拟信号是指-----时间和数值均连续变化的电信号&#xff0c;如正弦波、三角波等。 数字信号是指-----在时间上和数值上均是离散的…

小兔鲜项目 uniapp (1)

目录 项目架构 uni-app小兔鲜儿电商项目架构 小兔鲜儿电商课程安排 创建uni-app项目 1.通过HBuilderX创建 2.通过命令行创建 pages.json和tabBar案例 uni-app和原生小程序开发区别 用VS Code开发uni-app项目 拉取小兔鲜儿项目模板代码 基础架构–引入uni-ui组件库 操…