Java JDK8 Stream 使用详解

2023-11-18

Stream(流) 的 筛选/去重/截取跳过映射/合并多个流/匹配/归约 简单示例

1.什么是流?

流是Java8引入的全新概念,它用来处理集合中的数据,暂且可以把它理解为一种高级集合。
众所周知,集合操作非常麻烦,若要对集合进行筛选、投影,需要写大量的代码,而流是以声明的形式操作集合,它就像SQL语句,我们只需告诉流需要对集合进行什么操作,它就会自动进行操作,并将执行结果交给你,无需我们自己手写代码。
因此,流的集合操作对我们来说是透明的,我们只需向流下达命令,它就会自动把我们想要的结果给我们。由于操作过程完全由Java处理,因此它可以根据当前硬件环境选择最优的方法处理,我们也无需编写复杂又容易出错的多线程代码了。

2.流的特点

  1. 只能遍历一次
    我们可以把流想象成一条流水线,流水线的源头是我们的数据源(一个集合),数据源中的元素依次被输送到流水线上,我们可以在流水线上对元素进行各种操作。
    一旦元素走到了流水线的另一头,那么这些元素就被“消费掉了”,我们无法再对这个流进行操作。当然,我们可以从数据源那里再获得一个新的流重新遍历一遍。
  2. 采用内部迭代方式
    若要对集合进行处理,则需我们手写处理代码,这就叫做外部迭代。
    而要对流进行处理,我们只需告诉流我们需要什么结果,处理过程由流自行完成,这就称为内部迭代。

3.流的操作种类

流的操作分为两种,分别为中间操作和终端操作。

  1. 中间操作
    当数据源中的数据上了流水线后,这个过程对数据进行的所有操作都称为“中间操作”。
    中间操作仍然会返回一个流对象,因此多个中间操作可以串连起来形成一个流水线。
  2. 终端操作
    当所有的中间操作完成后,若要将数据从流水线上拿下来,则需要执行终端操作。
    终端操作将返回一个执行结果,这就是你想要的数据。

4.流的操作过程

使用流一共需要三步:

  1. 准备一个数据源
  2. 执行中间操作
    中间操作可以有多个,它们可以串连起来形成流水线。
  3. 执行终端操作
    执行终端操作后本次流结束,你将获得一个执行结果。

5. 使用流

下面就是对stream的具体使用和操作把注释和示例代码放在一起了。

public class StreamTest {

    public static void main(String[] args) {
        //1.通过Arrays类提供的静态函数stream()获取数组的流对象:
        String[] names = {"xiaohong","xiaoli","xiaohei"};
        Stream<String> stream = Arrays.stream(names);

        //2.直接将几个值变成流对象:
        Stream<String> stream1 = Stream.of("xiaohong", "xiaoli", "xiaohei");

        //3.filter 函数接收一个Lambda表达式作为参数,该表达式返回boolean,在执行过程中,流将元素逐一输送给filter,并筛选出执行结果为true的元素。
        //如,筛选出所有大于22岁学生:
        List<Student> studentList = new ArrayList<>();
        studentList.add(new Student("xiaoli",22));
        studentList.add(new Student("xiaohong",23));
        List<Student> studentList2  = studentList.stream().filter(s-> s.getAge() > 22).collect(Collectors.toList());
        System.out.println("studentList2:"+studentList2.toString());


        //4.去重distinct
        //去掉重复的结果:
        List<String> listDistinct = Arrays.asList("AA", "BB", "CC", "BB", "CC", "AA", "AA");
        listDistinct=  listDistinct.stream().distinct().collect(Collectors.toList());
        System.out.println("listDistinct:"+listDistinct.toString());

        //5.截取
        //截取流的前N个元素:
        List<String> listLimit = Arrays.asList("DD", "EE", "FF", "GG","AA", "BB", "CC");
        listLimit = listLimit.stream().limit(3).collect(Collectors.toList());
        System.out.println("listLimit:"+listLimit);

        //6.跳过
        //跳过流的前n个元素:
        List<String> listSkip = Arrays.asList("AA", "BB", "CC","DD", "EE", "FF", "GG");
        listSkip = listSkip.stream().skip(2).collect(Collectors.toList());
        System.out.println("listSkip:"+listSkip);

        //7.映射
        //对流中的每个元素执行一个函数,使得元素转换成另一种类型输出。流会将每一个元素输送给map函数,并执行map中的Lambda表达式,最后将执行结果存入一个新的流中。
        //如,获取每个人的姓名(实则是将Perosn类型转换成String类型):
        List<Student> studentListMap = new ArrayList<>();
        studentListMap.add(new Student("xiaoli",22));
        studentListMap.add(new Student("xiaohong",23));
        List<String> studentStr  = studentListMap.stream().map(Student::getName).collect(Collectors.toList());
        System.out.println("studentStr:"+studentStr);

        //8.合并多个流
        //例:列出List中各不相同的单词,List集合如下:
        List<String> listStr = new ArrayList<String>();
        listStr.add("I am a boy");
        listStr.add("I love the girl");
        listStr.add("But the girl loves another girl");
        //思路如下:
        //首先将list变成流:
        Stream<String> listStrStream = listStr.stream();
        //按空格分词:分完词之后,每个元素变成了一个String[]数组。将每个 String[] 变成流:
        //listStrStream
        //        .map(line->line.split(" ")).map(Arrays::stream);
        //此时一个大流里面包含了一个个小流,我们需要将这些小流合并成一个流。
        //将小流合并成一个大流:用 flatMap 替换刚才的 map
        //listStrStream.map(line -> line.split(" ")).flatMap(Arrays::stream);
        //去重
        List<String> stringList = listStrStream
                .map(line -> line.split(" "))
                .flatMap(Arrays::stream)
                .distinct()
                .collect(Collectors.toList());
        System.out.println("stringList:"+stringList);

        //9.是否匹配任一元素:anyMatch
        //anyMatch用于判断流中是否存在至少一个元素满足指定的条件,这个判断条件通过Lambda表达式传递给anyMatch,执行结果为boolean类型。
        //如,判断list中学生是否有>22岁:
        List<Student> studentListAnyMatch = new ArrayList<>();
        studentListAnyMatch.add(new Student("wanghua",22));
        studentListAnyMatch.add(new Student("yangzong",23));
        studentListAnyMatch.add(new Student("lijing",18));
        boolean studentListAnyMatchBool  = studentListAnyMatch.stream().anyMatch(s-> s.getAge() > 22);
        System.out.println("studentListAnyMatchBool:"+studentListAnyMatchBool);

        //10.是否匹配所有元素:allMatch
        //allMatch用于判断流中的所有元素是否都满足指定条件,这个判断条件通过Lambda表达式传递给anyMatch,执行结果为boolean类型。
        //如,判断是否所有人都>22岁:
        boolean allMatchBoll = studentListAnyMatch.stream().allMatch(s -> s.getAge() > 22);
        System.out.println("allMatchBoll:"+allMatchBoll);

        //11.是否未匹配所有元素:noneMatch
        //noneMatch与allMatch恰恰相反,它用于判断流中的所有元素是否都不满足指定条件:
        boolean noneMatchBoll = studentListAnyMatch.stream().noneMatch(s -> s.getAge() > 35);
        System.out.println("noneMatchBoll:"+noneMatchBoll);

        //12.获取任一元素findAny
        //findAny能够从流中随便选一个元素出来,它返回一个Optional类型的元素。
        Optional<Student> student = studentListAnyMatch.stream().findAny();
        Student studentFindAny = student.get();
        System.out.println("studentFindAny随机取出的是:"+studentFindAny);

        //13.获取第一个元素findFirst
        Optional<Student> firstStudent = studentListAnyMatch.stream().findFirst();
        System.out.println("firstStudent:"+firstStudent.get());

        //14.归约
        //归约是将集合中的所有元素经过指定运算,折叠成一个元素输出,如:求最值、平均数等,这些操作都是将一个集合的元素折叠成一个元素输出。
        //在流中,reduce函数能实现归约。
        //reduce函数接收两个参数:
        //1. 初始值
        //2. 进行归约操作的Lambda表达式
        //元素求和:自定义Lambda表达式实现求和
        //例:
        List<Integer> listReduce = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
        Integer sumReduce = listReduce.stream().reduce(0, Integer::sum);
        System.out.println("sumReduce:"+sumReduce);
        //Integer类还提供了 min、max 等一系列数值操作,当流中元素为数值类型时可以直接使用。

        //15.数值流的使用
        //采用reduce进行数值操作会涉及到基本数值类型和引用数值类型之间的装箱、拆箱操作,因此效率较低。
        //当流操作为纯数值操作时,使用数值流能获得较高的效率。
        //将普通流转换成数值流
        //StreamAPI提供了三种数值流:IntStream、DoubleStream、LongStream,也提供了将普通流转换成数值流的三种方法:mapToInt、mapToDouble、mapToLong。
        //如,将Student中的age转换成数值流:
        IntStream intStudentStream = studentListAnyMatch.stream().mapToInt(Student::getAge);
        //数值计算
        //每种数值流都提供了数值计算函数,如max、min、sum等。如,找出最大的年龄:
        OptionalInt maxAge = intStudentStream.max();
        System.out.println("maxAge:"+maxAge.getAsInt());
        //由于数值流可能为空,并且给空的数值流计算最大值是没有意义的,因此max函数返回OptionalInt,它是Optional的一个子类,能够判断流是否为空,并对流为空的情况作相应的处理。
        //此外,mapToInt、mapToDouble、mapToLong进行数值操作后的返回结果分别为:OptionalInt、OptionalDouble、OptionalLong


    }


}

若有错误,希望大佬指出。
对你有帮助给点个

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java JDK8 Stream 使用详解 的相关文章

  • 我在socket上设置了超时,发现这个值不能大于21

    我在socket上设置了超时 该值小于21秒才有效 21秒后发现超时还是21秒 public static void main String args SimpleDateFormat sdf new SimpleDateFormat yy
  • 在Java中使用命令行编译多个包

    您好 我一直在使用 IDE 但现在我需要从命令行运行和编译 问题是我有多个软件包 我试图找到答案 但没有任何效果 所以我有 src Support java files Me java files Wrapers java files 你知
  • 将 Hibernate 对象序列化为 JSON 时抛出异常

    好吧 我正在使用 Hibernate 将一个小型数据库加载到一些表示表的类并与数据库交互 一切都很好 我真的可以看到所有结果 而且我没有任何空字段 所有这些都已被使用 这里我展示了 主 类 表 import javax persistenc
  • 手动编辑 Jar 以更改包名称

    我有一个来自外部源的 jar 文件 jar 中的所有类都位于 com xyz 包中 我想将所有类移动到 com xyzold 包中 这是否像解压缩 jar 将 xzy 文件夹重命名为 xyzold 并重新压缩它一样简单 或者我还需要修改每个
  • 防止 Spring Boot 注册 Spring Security 过滤器之一

    我想禁用安全链中的 Spring Security 过滤器之一 我已经看到了防止 Spring Boot 注册 servlet 过滤器 https stackoverflow com questions 28421966 prevent s
  • 在哪里可以获得有关 Java FitNesse 和 Slim 的一些教程? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 使用 ChannelExec 的命令未执行 - Jsch

    我正在使用 Jsch 在服务器中创建一个文件并执行一些命令 对于文件创建 它工作正常 但是对于命令执行 则不然 它保持状态 1 仍在处理它 并永远保持该状态 这种情况发生在 shell 执行或我尝试成为 root 时 请按照以下方法操作 p
  • 如何拦截 REST 端点以接收所有标头?

    我当前的代码是 Path login RequestScoped public class LoginResource GET SecurityChecked public Response getUser HeaderParam AUTH
  • 字符串池可以包含两个具有相同值的字符串吗? [复制]

    这个问题在这里已经有答案了 字符串池可以包含两个具有相同值的字符串吗 String str abc String str1 new String abc Will the second statement with new operator
  • Java Microsoft Excel API [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • JFace ColumnWeigthData 导致父级增长

    我有一个 Eclipse RCP 应用程序 并且想要在TableViewer using ColumnWeigthData as ColumnLayoutData 问题是父表单 ScrolledForm在示例代码中 每当我布局表格时都会增加
  • 容器中的 JVM 计算处理器错误?

    最近我又做了一些研究 偶然发现了这一点 在向 OpenJDK 团队抱怨之前 我想看看是否有其他人观察到这一点 或者不同意我的结论 因此 众所周知 JVM 长期以来忽略了应用于 cgroup 的内存限制 众所周知 现在从 Java 8 更新某
  • Java-如何将黑白图像加载到二进制中?

    我在 FSE 模式下使用 Java 和 swing 我想将完全黑白图像加载为二进制格式 最好是二维数组 并将其用于基于掩码的每像素碰撞检测 我什至不知道从哪里开始 过去一个小时我一直在研究 但没有找到任何相关的东西 只需将其读入Buffer
  • 所有平台上的java

    如果您想用 java 为 Windows Mac 和 Linux 编写桌面应用程序 那么所有这些代码都相同吗 您只需更改 GUI 即可使 Windows 应用程序更像 Windows 等等 如果不深入细节 它是如何工作的 Java 的卖点之
  • 带有 OpenId 提供程序的 Java Spring 安全性

    我有一个 spring MVC 应用程序 另一个客户端应用程序想要使用 open id connect 访问我的 spring 应用程序 如何在服务器端实现开放ID提供商 请帮忙 MITREid 连接 OpenID Connect Java
  • 为什么我的代码会产生错误:该语句没有返回结果集[重复]

    这个问题在这里已经有答案了 我正在从 Microsoft SQL Server Studio 执行以下查询 该查询工作正常并显示结果 SELECT INTO temp table FROM md criteria join WHERE us
  • 摩尔斯电码 至 英语

    我现在的问题是让 摩尔斯电码转英语 正常工作 将英语转换为莫尔斯电码的第一部分工作正常 我知道以前已经有人问过这个问题 但我不知道我做错了什么 我知道我需要在某个地方进行拆分 但我只是不确定将其放在代码中的何处 现在 莫尔斯电码到英语的部分
  • 每次我们调用浏览器时,在 selenium 中使用 driver.manage().window().maximize() 是否好?

    We use driver manage window maximize 最大化浏览器 我在网上看到一些使用的例子driver manage window maximize 尽管不需要最大化浏览器 例如 gmail 登录 我还看到使用 se
  • 为什么范围为“provided”的依赖项会隐藏 Maven 中的传递依赖项?

    我的 Maven 项目中有三个模块 这稍微简化了 model包含JPA注释的实体类 坚持实例化一个实体管理器并调用它的方法 应用创建类的实例model 设置一些值并将它们传递给坚持 model and 坚持显然取决于javax persis
  • Java、Spring、Hibernate找不到org.springframework.orm.hibernate3.LocalSessionFactoryBean

    我正在尝试制作 spring hibernate ant 项目 目前我收到此错误 HTTP Status 500 type Exception report message description The server encountere

随机推荐

  • 2023安徽省“中银杯”职业技能大赛“网络安全” 项目比赛任务书

    2023安徽省 中银杯 职业技能大赛 网络安全 项目比赛任务书 2023安徽省 中银杯 职业技能大赛 网络安全 项目比赛任务书 A模块基础设施设置 安全加固 200分 A 1 登录安全加固 Windows Linux A 2 Nginx安全
  • 论文纠错(一)

    说说最近读的几篇论文的问题 果然有的论文还是不能细细地去读 一读就发现有问题 第一个是MSPCA里面的公式 7 到公式 8 那个Sr前面的2是不应该有的 也就是推导的时候出错了 第二个是GPUTENSOR里面的Gpu product的算法
  • BeyondCompare4破解

    转自 跳不出循环了 原文链接 https blog csdn net weixin 39298366 article details 84390224 将以下操作保存为bat文件 然后双击运行即可 reg delete HKEY CURRE
  • Flask数据库插件安装与配置教程

    Flask数据库插件安装与配置教程 数据插件安装 Flask使用数据库之前需要在python中安装额外的插件 这里主要用到Flask script 命令扩展解释器 PyMySQL 数据库驱动 Flask SQLAchemy ORM映射 和F
  • 【python实现网络爬虫22】唯品会商品信息实战步骤详解

    唯品会商品信息实战 1 目标网址和页面解析 2 爬虫初探 3 爬虫实操 3 1 进行商品id信息的爬取 3 2 商品id数据url构造 3 3 商品id数据格式转化及数量验证 3 4 商品详细信息获取 4 全部代码 手动反爬虫 原博地址 知
  • 可以用filament的示例material_sandbox来调整obj的pbr渲染参数,也有个gltf_viewer读取gltf模型

    如题 说不准以后导出文件就不用cesiumlab了 具体待查
  • 编程获取图像中的圆半径

    版权声明 本文为博主原创文章 转载请在显著位置标明本文出处以及作者网名 未经作者允许不得用于商业目的 即将推出EmguCV的教程 请大家还稍作等待 之前网友咨询如何获得图像中圆形的半径 其中有两个十字作为标定 十字之间距离为100mm 如下
  • 【每日运维】U盘启动盘安装 ESXi 6.7.0 安装卡在 loading /bnxtroce.v00

    问题描述 ESXi 6 7 0 安装进度卡在loading bnxtroce v00 进度处 处理方法 重新制作启动盘 写入方式改为 USB ZIP v2 设置服务器的 bios设置 启动方式改为 UEFI 重启开机安装即可
  • 打印数字三角及蛇形矩阵(C语言)

    题目描述 从键盘输入N 输出如下图所示的N行的数字三角 例如 N 5 那么输出如下 输入格式 输入一个整数N 1 lt N lt 45 输出格式 输出如题所示的数字三角形 为了输出美观 每个数字栈5个字符位 右对齐 即 5d 解题的思路 1
  • ISP(五) RGB、YUV与YCbCr的概念详解

    一 概念 首先要说明RGB YUV和YCbCr都是人为规定的彩色模型或颜色空间 有时也叫彩色系统或彩色空间 它的用途是在某些标准下用通常可接受的方式对彩色加以描述 1 RGB 红绿蓝 是依据人眼识别的颜色定义出的空间 可表示大部分颜色 但在
  • 浅谈逻辑漏洞中的越权访问漏洞

    越权漏洞 越权访问漏洞示意图 一 越权访问漏洞简介 1 类型 水平越权 通过更换的某个ID之类的身份标识 从而使A账号获得 增删查改 B账号的数据 垂直越权 使用低权限身份的账号 发送高权限账号的请求 获得其高权限的操作 未授权访问 通过删
  • Vue--ElementUI组件库

    1 概述 Element官网 ElementUI是饿了么前端团队推出的一款基于Vue桌面端UI框架 和Boostrap一样对原生的HTML标签进行了封装 美化 让我们能够专注于业务逻辑而不是UI界面 默认情况下无论我们有没有使用到某个组件
  • JVM类加载器的urlclassloader和appclassloader

    package kite jvm import java net URL 首先为什么 1 可以 因为OneURLClassLoader在加载Constant的时候发现需要加载 OneInterface 因为他是其接口 因为OneURLCla
  • merkle tree

    merkle tree 是用来存储hash值的一棵树 其叶子是数据块的hash值 非叶子节点是其对应子节点的串联字符串的hash hash是一个把任意长度数据映射成固定长度的函数 对于数据完整性校验 最简单的方法是对整个数据做Hash运算得
  • elasticsearch对数组进行搜索

    写在前面 我们在进行全文建搜的时候往往会添加很多前置条件 比如地区 时间 以及知识点树 我们需要在搜索之前先进行过滤在进行搜索 Array索引 es的数据类型中实际上是不包含数组类型的 在默认的情况下任何字段都可以包含0或者是更多的值 并且
  • docker配置nginx

    docker配置nginx 1 首先安装nginx镜像 docker pull nginx 安装好可以选择测试 也可以跳过 测试命令两行 docker run name nginx test p 80 80 d nginx docker s
  • OC 6702升压型恒流驱动芯片, ESOP8 封装,内置 100V 功率 MOS

    概述 OC 6702 是一款内置 100V 功率 NMOS 高效率 高精度的升压型大功率 LED 恒流驱动芯片 OC6702 采用固定关断时间的控制方 式 关断时间可通过外部电容进行调节 工作频率可根据用户要求而改变 OC6702 通过调节
  • 判断一个对象是否有空的属性值

    直接上代码 const trim str gt const newStr str 0 str str toString return newStr newStr replace s s g str 判断一个对象是否有空的属性值 const
  • 树莓派配置wifi做热点方法

    http wiki jikexueyuan com project raspberry pi wifi html
  • Java JDK8 Stream 使用详解

    Stream 流 的 筛选 去重 截取跳过映射 合并多个流 匹配 归约 简单示例 1 什么是流 2 流的特点 3 流的操作种类 4 流的操作过程 5 使用流 1 什么是流 流是Java8引入的全新概念 它用来处理集合中的数据 暂且可以把它理