Java 基础进阶篇(十二)—— Stream 流常用方法总结

news2025/1/16 19:55:00

文章目录

  • 一、Stream流概述
  • 二、获取Stream流
    • 2.1 集合获取 Stream 流
    • 2.2 数组获取 Stream 流
  • 三、中间方法
  • 四、终结方法
  • 五、Stream流的综合应用
  • 六、收集Stream流


一、Stream流概述

Stream 流是在 Java8 中,得益于 Lambda 所带来的函数式编程, 引入了一个全新的 Stream 流概念。

目的:用于简化集合和数组操作的API。

Stream 流思想:先得到集合或者数组的 Stream 流(就是一根传送带);把元素放上去;然后就用这个 Stream 流简化的 API 来方便的操作元素

Stream 流的三类方法

① 获取 Stream 流:创建一条流水线,并把数据放到流水线上准备进行操作。
② 中间方法:流水线上的操作,一次操作完毕之后,还可以继续进行其他操作。
③ 终结方法:一个Stream流只能有一个终结方法,是流水线上的最后一个操作。


二、获取Stream流

Stream 操作集合或者数组的第一步是先得到 Stream 流,然后才能使用流的功能。

2.1 集合获取 Stream 流

Collection 系列集合:默认方法 stream​() 生成流。

在这里插入图片描述

Collection<String> list = new ArrayList<>();
Stream<String> s1 = list.stream();

Map 系列集合使用 stream() 方法获取键流、值流、键值对的流。

Map<String, Integer> map = new HashMap<>();
// 键流
Stream<String> s2 = map.keySet().stream();
// 值流
Stream<Integer> s3 = map.values().stream();
// 键值对
Stream<Map.Entry<String, Integer>> s4 = map.entrySet().stream();

2.2 数组获取 Stream 流

String[] strs = {"张三丰", "灭绝师太", "东方不败"};
Stream<String> s5 = Arrays.stream(strs);
Stream<String> s6 = Stream.of(strs);

三、中间方法

Stream 流的中间方法,即中间操作方法,也称为非终结方法。常用的 API 如下:

在这里插入图片描述

注意:调用完成后返回新的 Stream 流可以继续使用,支持链式编程;在 Stream 流中无法直接修改集合、数组中的数据


四、终结方法

Stream 流的终结方法,即终结操作方法。常用的 API 如下:在这里插入代码片

在这里插入图片描述

注意:终结操作方法,调用完成后流就无法继续使用了,原因是不会返回 Stream 流。


五、Stream流的综合应用

案例1:从集合中找到姓张,且名称长度是3的姓名。

public class StreamDemo1 {
    public static void main(String[] args) {
        ArrayList<String> names = new ArrayList<>();
        Collections.addAll(names, "张三丰", "张无忌", "张三", "李四", "李明", "张强");
   
        // 从集合中找到姓张,且名称长度是3的姓名。
        names.stream().filter(new Predicate<String>() {
            @Override
            public boolean test(String s) {
                return s.startsWith("张");
            }
        }).filter(new Predicate<String>() {
            @Override
            public boolean test(String s) {
                return s.length()==3;
            }
        }).forEach(new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        });
        // Lambda 化简
        names.stream().filter(s -> s.startsWith("张")).filter(s -> s.length()==3).forEach(s-> System.out.println(s));
        names.stream().filter(s -> s.startsWith("张")&&s.length()==3).forEach(System.out::println);
    }
}

案例2:测试 map 加工方法

public class StreamDemo2 {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        Collections.addAll(list, "张三丰", "张无忌", "张三", "李四", "李明", "张强");
        
        // map加工方法
        // new Function<String, String>() 第一个参数原材料,第二个参数是加工后的结果。
        // 1. 需求1:给集合元素的前面都加上一个:黑马的:
        list.stream().map(new Function<String, String>() {
            @Override
            public String apply(String s) { // 形参类型是第一个参数,方法返回类型是第二个参数
                return "黑马的" + s;
            }
        });
        // Lambda 化简
        list.stream().map(s -> "黑马的" + s).forEach(System.out::println);


        // 2. 需求2:把所有的名称 都加工成一个学生对象。
        list.stream().map(new Function<String, Student>() {
            @Override
            public Student apply(String s) {
                return new Student(s);
            }
        });
        list.stream().map(s -> new Student(s)).forEach(System.out::println);
        list.stream().map(Student::new).forEach(System.out::println); // 构造器引用,方法引用
    }
}

案例3:测试合并流

public class StreamDemo3 {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        Collections.addAll(list, "张三丰", "张无忌", "张三", "李四", "李明", "张强");

        // 合并流
        Stream<String> s1 = list.stream().filter(s -> s.startsWith("张"));
        Stream<String> s2 = Stream.of("java1", "java2");
        // public static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b)
        Stream<String> s3 = Stream.concat(s1, s2);
        //s3.forEach(System.out::println);
        s3.distinct().forEach(System.out::println); // 去重后输出

        // distinct 依赖 hasCode 和 equals 方法
        ArrayList<Student> students = new ArrayList<>();
        Collections.addAll(students, new Student("张无忌"), new Student("张无忌"), new Student("张三丰"), new Student("张三丰"), new Student("李有田"));
        students.stream().distinct().forEach(System.out::println); // Student{name='张无忌'}, Student{name='张三丰'}Student{name='李有田'}
    }
}

六、收集Stream流

收集 Stream 流,就是把 Stream 流操作后的结果数据转回到集合或者数组中去。

Stream流只是方便操作集合/数组的手段,得到集合/数组才是开发中的目的

Stream 流的收集方法:
在这里插入图片描述
Collectors 工具类提供了具体的收集方式:

在这里插入图片描述

public class StreamDemo5 {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        Collections.addAll(list, "张无忌", "周芷若", "赵敏", "张强", "张三丰", "张三丰");
        
        Stream<String> s1 = list.stream().filter(s -> s.startsWith("张"));
        List<String> zhangList = s1.collect(Collectors.toList());
        //List<String> zhangList = s1.toList(); // jdk16新添加方法 这种写法,返回不可变集合
        zhangList.add("新添加的元素"); //  如果添加元素 s1.toList(),方法会报错
        System.out.println(zhangList); // [张无忌, 张强, 张三丰, 张三丰, 新添加的元素]

        // 注意:流只能使用一次,若要重新使用流,需要重新定义
        Stream<String> s2 = list.stream().filter(s -> s.startsWith("张"));
        Set<String> zhangSet = s2.collect(Collectors.toSet()); // 收集成Set
        System.out.println(zhangSet); // [张强, 张三丰, 张无忌]

        Stream<String> s3 = list.stream().filter(s -> s.startsWith("张"));
        Object[] arrs = s3.toArray();// 收集成数组
        System.out.println(Arrays.toString(arrs)); // [张无忌, 张强, 张三丰, 张三丰]

        // 拓展:收集成指定流,如 String 流
        Stream<String> s4 = list.stream().filter(s -> s.startsWith("张"));
        String[] array = s4.toArray(new IntFunction<String[]>() {
            @Override
            public String[] apply(int value) {
                return new String[value];
            }
        });// 收集成数组

        // String[] array = s4.toArray( value -> new String[value] );
        // String[] array = s4.toArray(String[]::new);
        System.out.println(Arrays.toString(array)); // [张无忌, 张强, 张三丰, 张三丰]
    }
}

文章参考:Java入门基础视频教程,java零基础自学就选黑马程序员Java入门教程(含Java项目和Java真题)

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

前端技术——css

1.CSS的引入 【1】为什么要学习CSS? 如果只用HEML画页面的话--->这个页面就是页面上需要的元素罗列起来&#xff0c;但是页面效果很差&#xff0c;不好看&#xff0c;为了让页面好看&#xff0c;为了修饰页面。所以我们需要用到CSS。 CSS的作用&#xff1a;修饰HTML页面…

总结844

学习目标&#xff1a; 月目标&#xff1a;5月&#xff08;张宇强化前10讲&#xff0c;背诵15篇短文&#xff0c;熟词僻义300词基础词&#xff09; 周目标&#xff1a;张宇强化前3讲并完成相应的习题并记录&#xff0c;英语背3篇文章并回诵 每日必复习&#xff08;5分钟&#…

密码学:流密码.(对称密码)

密码学&#xff1a;流密码. 流密码(Stream Cipher)属于对称密码算法中的一种&#xff0c;其基本特征是加解密双方使用一串与明文长度相同的密钥流&#xff0c;与明文流组合来进行加解密密钥流通常是由某一确定状态的伪随机数发生器所产生的比特流&#xff0c;双方将伪随机数生…

数据结构-二叉树遍历线索二叉树

目录 一、二叉树的定义 *几种特殊的二叉树 *二、二叉树的性质 三、二叉树的存储结构 *四、二叉树的遍历 *4.1先序遍历 * 4.2中序遍历 * 4.3后序遍历 非递归算法遍历 *4.4层序遍历 *五、遍历序列构造二叉树 六、线索二叉树 6.1逻辑结构: * 6.2构造线索二叉树 一、二…

Mybatis Plus | 快速入门

&#x1f497;wei_shuo的个人主页 &#x1f4ab;wei_shuo的学习社区 &#x1f310;Hello World &#xff01; Mybatis Plus MyBatis-Plus&#xff08;简称 MP&#xff09;是一个基于 MyBatis 的增强工具&#xff0c;它对 Mybatis 的基础功能进行了增强&#xff0c;但未做任何改…

Qt 多语言界面设计概述

1、多语言界面设计概述 有些软件需要开发多语言界面版本&#xff0c;如中文版和英文版&#xff0c;并且在软件里可以方便地切换界面语言。Qt 为多语言界面提供了很好的支持&#xff0c;使用 Qt 的一些规则和工具&#xff0c;可以很方便地为应用程序开发提供多语言界面支持。 …

Shell脚本函数简介及运用(喜欢,适合,能在一起,是三码事)

一、函数的作用 语句块定义成函数约等于别名&#xff0c;定义函数&#xff0c;再引用函数 封装的可重复利用的具有特定功能的代码 二、定义函数 定义函数就是只将一段实现某个任务的命令序列封装进一个函数&#xff0c;便于使用和后期维护。 function 函数名() { 命令序列 }…

快速原型设计工具(Axure)的安装、汉化

〇、一些名词解释&#xff1a; 1. 草图 一般主要用于产品整理思路&#xff0c;寻找灵感&#xff0c;或者在产品团队内部互相讨论碰撞火花时使用。画 给自己看的&#xff0c;想怎么画就怎么画。 2. 低保真 打个比喻来说就像&#xff0c;用于“生产的图纸”&#xff0c;要简单易读…

Postgres:Win/Linux环境安装及一键部署脚本

1.Win安装Postgres &#xff08;1&#xff09;下载安装包 &#xff08;2&#xff09;开始安装 修改安装目录 选择要安装的组件 data也就是库表及数据的.dba文件存放目录 密码设置 端口设置 next next 开始安装 安装完成&#xff0c;Stack Builder 根据需要选择是否安装。仅仅是…

03-Docker容器命令

新建启动容器 docker run [OPTIONS] IMAGE [COMMAND] [ARG...]常用的参数&#xff1a; --namenew_name&#xff1a;为容器指定一个名称-d&#xff1a;后台运行容器并返回容器ID&#xff0c;即启动守护式容器-i&#xff1a;以交互模式&#xff08;interactive&#xff09;运行…

【三十天精通Vue 3】第二十九天 Vue 3中的Mock数据模拟详解

✅创作者:陈书予 🎉个人主页:陈书予的个人主页 🍁陈书予的个人社区,欢迎你的加入: 陈书予的社区 🌟专栏地址: 三十天精通 Vue 3 文章目录 引言一、Mock数据模拟的概述1.1 为什么需要Mock数据模拟?1.2 Mock数据模拟的优点和缺点二、安装和配置Mock.js库2.1 使用NPM安…

TIA博途Wincc通过区域指针中的作业信箱功能实现自动写入配方数据的具体方法

TIA博途Wincc通过区域指针中的作业信箱功能实现自动写入配方数据的具体方法 前面和大家分享了博途Wincc中配方功能的具体使用方法,具体内容可参考以下链接中的内容: TIA博途Wincc中自定义配方画面的具体方法示例 上面的例子中,向PLC写入数据时是通过点击屏幕上的按钮来实现…

scrapy爬虫标准流程

Scrapy爬虫的标准流程一般包括以下几个步骤&#xff1a; 1、明确需求和目标网站的结构&#xff0c;确定需要爬取的数据以及爬取规则。 2、创建一个Scrapy项目&#xff0c;使用命令行工具创建一个新的Scrapy项目。 3、定义数据模型和item&#xff0c;即确定要爬取的数据结构。…

基于SpringBoot开发的仓库管理系统

系统概要 仓库管理系统总共分为两个大的模块&#xff0c;分别是系统模块和业务模块。其中系统模块和业务模块底下又有其子模块。 功能模块 一、业务模块 1、客户管理 客户列表 客户分页和模糊查询 客户添加、修改、删除、批量删除 2、供应商管理 供应商列表 供应商分…

sql注入合集

1.Access注入 http://110.40.154.212:8002/Production/PRODUCT_DETAIL.asp?id1513 and exists(select count(*) from admin) #存在admin表&#xff0c;继续爆&#xff0c;还存在job,email,product等http://110.40.154.212:8002/Production/PRODUCT_DETAIL.asp?id1513 and e…

软考A计划-重点考点-专题二(程序语言)

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分享&am…

GP04丨网格框架初版

量化策略开发&#xff0c;高质量社群&#xff0c;交易思路分享等相关内容 正文 大家好&#xff0c;今天我们分享股票社群第4期量化策略——网格策略。 在上一期中&#xff0c;我们分享了ETF轮动策略Plus版本&#xff08;基于资金管理的ETF增强策略&#xff09;&#xff0c;本…

Linux-Day02

Linux-Day02 课程内容 软件安装 项目部署 1. 软件安装 1.1 软件安装方式 在Linux系统中&#xff0c;安装软件的方式主要有四种&#xff0c;这四种安装方式的特点如下&#xff1a; 安装方式特点二进制发布包安装软件已经针对具体平台编译打包发布&#xff0c;只要解压&am…

哪种蓝牙耳机音质最好佩戴舒服?佩戴舒适音质好的蓝牙耳机

蓝牙无线耳机基本成为了大家的标配&#xff0c;大多数 对于外观与舒适性十分看重&#xff0c;如今的蓝牙耳机市场已经很成熟了&#xff0c;基本能满足大多数人&#xff0c;下面就来分享几款佩戴并且音质表现也不错的蓝牙耳机。 一、南卡小音舱Lite2蓝牙耳机 参考价格&#xf…

【机器人仿真Webots教程】-控制器编程指南

Webots controller编程指南 文章目录 Webots controller编程指南1. controller程序设计流程1.1 controller与场景树节点1.2 进程角度分析1.3 仿真时间步长与控制器程序更新延时步长 2. 例解控制器编程2.1 Hello world 实例2.2 传感器读取实例2.3 执行器的使用2.4 传感器与执行器…