Java 8:Stream API 流式操作

news2024/11/23 11:39:15

在这里插入图片描述

💗wei_shuo的个人主页

💫wei_shuo的学习社区

🌐Hello World !


Java 8:Stream API

Java 8 中的 Stream API 是一组用于对集合数据进行处理的新特性;提供一种以声明式风格对集合进行操作的方式,简化集合的处理,使得代码更加简洁、优雅,并且能够更高效地处理数据;

这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等;元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果

+--------------------+       +------+   +------+   +---+   +-------+
| stream of elements +-----> |filter+-> |sorted+-> |map+-> |collect|
+--------------------+       +------+   +------+   +---+   +-------+

流程转换为 Java 代码为:

List<Integer> transactionsIds = 
widgets.stream()
             .filter(b -> b.getColor() == RED)
             .sorted((x,y) -> x.getWeight() - y.getWeight())
             .mapToInt(Widget::getWeight)
             .sum();

特性

声明式编程风格:Stream API 提供了类似于 SQL 查询的声明式编程方式,通过链式调用一系列方法来对数据进行操作,而不是显式地编写循环或临时变量。这使得代码更加简洁、易读和易于理解

惰性求值:Stream 是惰性求值的,即只有在终止操作时才会真正执行;中间操作(如 filter、map、sorted 等)只是定义了数据流的处理步骤,而不会立即执行;这样可以优化处理过程,避免不必要的计算,提高性能

函数式接口支持:Stream API 需要与函数式接口(Functional Interface)一起使用;函数式接口是只包含一个抽象方法的接口,Lambda 表达式可以作为函数式接口的实例进行传递;这种支持使得 Stream API 能够充分发挥函数式编程的优势

生成流

Java 8 中, 集合接口有两个方法来生成流

stream():为集合创建串行流

parallelStream() −:为集合创建并行流

List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());

strings 列表创建了一个流,通过 stream() 方法将列表转换成了一个流;然后,使用 filter 方法传递一个 Lambda 表达式来筛选(过滤)不满足条件的元素;在这里,Lambda 表达式 string -> !string.isEmpty() 检查字符串是否非空;只有在字符串不为空的情况下,该元素会被保留在流中;最后,使用 collect 方法,结合 Collectors.toList() 收集器,将符合条件的元素收集到一个新的列表 filtered 中

流式操作

forEach

Stream 提供了新的方法 forEach 来迭代流中的每个数据:以下代码片段使用 forEach 输出10个随机数:

ints() 方法用于生成一个无限的随机整数流

Random random = new Random();
random.ints().limit(10).forEach(System.out::println);

map

map 方法用于映射每个元素到对应的结果:以下代码片段使用 map 输出了元素对应的平方数

List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
// 获取对应的平方数
List<Integer> squaresList = numbers.stream().map( i -> i*i).distinct().collect(Collectors.toList());

filter

filter 方法用于通过设置的条件过滤出元素:以下代码片段使用 filter 方法过滤出空字符串

List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
// 获取空字符串的数量
long count = strings.stream().filter(string -> string.isEmpty()).count();

limit

limit 方法用于获取指定数量的流:以下代码片段使用 limit 方法打印出 10 条数据

Random random = new Random();
random.ints().limit(10).forEach(System.out::println);

sorted

sorted 方法用于对流进行排序:以下代码片段使用 sorted 方法对输出的 10 个随机数进行排序

Random random = new Random();
random.ints().limit(10).sorted().forEach(System.out::println);

并行(parallel)程序

parallelStream 是流并行处理程序的代替方法:以下实例我们使用 parallelStream 来输出空字符串的数量

List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
// 获取空字符串的数量
long count = strings.parallelStream().filter(string -> string.isEmpty()).count();

Collectors

Collectors 类实现了很多归约操作,例如将流转换成集合和聚合元素:Collectors 可用于返回列表或字符串

List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
 
System.out.println("筛选列表: " + filtered);
String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(", "));
System.out.println("合并字符串: " + mergedString);

统计

产生统计结果的收集器;它们主要用于int、double、long等基本类型上,它们可以用来产生类似如下的统计结果

List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
 
IntSummaryStatistics stats = numbers.stream().mapToInt((x) -> x).summaryStatistics();
 
System.out.println("列表中最大的数 : " + stats.getMax());
System.out.println("列表中最小的数 : " + stats.getMin());
System.out.println("所有数之和 : " + stats.getSum());
System.out.println("平均数 : " + stats.getAverage());

map 操作

Stream API 中三种常见的 map 操作:mapmapToIntflatMap

  • map:用于将流中的元素映射为另一种类型的流。例如,将一个对象流中的每个对象映射为对象的某个属性值组成的流
  • mapToInt:用于将流中的元素映射为 IntStream,即基本类型 int 的流。它通常用于将流中的元素映射为整数值
  • flatMap:用于将流中的每个元素映射为一个流,然后将这些流连接成一个单一的流。它通常用于扁平化处理嵌套的流结构

案例

systemApplicationTypeRepo.list(new QueryWrapper<SystemApplicationType>().orderByAsc(SystemApplicationTypeCol.ID))
                .stream().map(bean -> new ResCommonIdNameCode(bean.getId(), bean.getName(), bean.getName())).collect(Collectors.toList()
systemApplicationTypeRepo.list(...):这部分代码使用了一个名为 systemApplicationTypeRepo 的仓库(Repository),通过调用 list 方法来查询数据库中的数据;list 方法接受一个查询条件对象 QueryWrapper<SystemApplicationType> 作为参数,用于指定查询条件

new QueryWrapper<SystemApplicationType>().orderByAsc(SystemApplicationTypeCol.ID):这是创建一个查询条件对象的过程;QueryWrapper 是 MyBatis-Plus 提供的用于构建查询条件的工具;orderByAsc(SystemApplicationTypeCol.ID) 表示按照 SystemApplicationType 实体类中 ID 字段的升序进行排序。

.stream():这将查询结果转换为一个 Stream<SystemApplicationType> 对象,便于后续的操作

.map(bean -> new ResCommonIdNameCode(bean.getId(), bean.getName(), bean.getName())):这部分使用 map 操作将查询结果的每个 SystemApplicationType 对象映射为 ResCommonIdNameCode 对象;ResCommonIdNameCode 是一个自定义的类,构造函数接受 id、name 和 code 作为参数,用于创建一个新的对象

.collect(Collectors.toList()):最后,使用 collect 方法将 Stream<ResCommonIdNameCode> 对象收集为 List<ResCommonIdNameCode>,即最终的结果列表
noticeResponses.stream()
                .sorted(Comparator.comparing(SystemNoticeResponse::getReadStatus)
                        .thenComparing(Comparator.comparing(SystemNoticeResponse::getCreateAt).reversed()))
                .collect(Collectors.toList());
.stream():将 noticeResponses 列表转换为一个 Stream<SystemNoticeResponse> 对象,使其能够使用 Stream API 提供的操作

.sorted(...):这是一个中间操作,用于对流中的元素进行排序;使用 Comparator.comparing(...) 方法创建了一个比较器,用于指定排序的规则;首先,按照 SystemNoticeResponse 对象的 readStatus 字段进行升序排序;.thenComparing(...) 表示如果 readStatus 相同,则按照 createAt 字段进行降序排序(使用 reversed() 方法)

.collect(Collectors.toList()):最后,使用 collect 方法将排序后的 Stream<SystemNoticeResponse> 对象收集为一个新的 List<SystemNoticeResponse>,即排序后的 noticeResponses 列表

🌼 结语:创作不易,如果觉得博主的文章赏心悦目,还请——点赞👍收藏⭐️评论📝


在这里插入图片描述

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

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

相关文章

pdf加水印怎么加?掌握这几种加水印方法就够了

pdf加水印怎么加&#xff1f;水印可以帮助保护你的文档免受未经授权的复制或滥用。通过在PDF文件上添加水印&#xff0c;可以在每页或指定位置显示作者、公司名称、版权信息或其他标识&#xff0c;以确保他人无法随意盗用你的作品。下面就给大家介绍几种添加水印的方法。 【迅捷…

Openlayers 实战 - 地图视野(View)- 图层 -(layer)- 资源(source)显示等级设置。

Openlayers 实战 - 地图视野&#xff08;View&#xff09;- 图层 -&#xff08;layer&#xff09;- 资源&#xff08;source&#xff09;显示等级设置。 问题原因核心代码完整代码&#xff1a;在线示例 在以往的项目维护中&#xff0c;出现一个问题&#xff0c;使用最新高清底图…

JS图表库LightningChart JS全新发布v4.2——新增多种雷达图表类型

LightningChartJS是Web上性能最高的图表库具有出色的执行性能 - 使用高数据速率同时监控数十个数据源。 GPU加速和WebGL渲染确保您的设备的图形处理器得到有效利用&#xff0c;从而实现高刷新率和流畅的动画。用于贸易&#xff0c;工程&#xff0c;航空航天&#xff0c;医药和其…

随机过程的2个例题探讨

&#xff08;一&#xff09;马氏过程和泊松过程、维纳过程的联系 泊松过程、维纳过程两者都是独立增量过程。独立增量过程是马氏过程的条件&#xff1a; 1. 随机过程是独立增量过程 2. X&#xff08;0&#xff09; 0 满足以上两个条件的随机过程都是马氏过程。 注意&#xff1…

C/C++test两步完成CMake项目静态分析

您可能一直在静态分析中使用CMake。但您是否尝试过将Parasoft C/Ctest与CMake一起使用吗&#xff1f;以下是如何使用C/Ctest在基于CMake的项目中运行静态分析的详细说明。 CMake是用于构建、测试和打包软件的最流行的工具之一。Parasoft C/Ctest通过简化构建管理过程&#xff…

Vue常用属性(计算属性和侦听器属性)

目录 计算属性computed 名称例子&#xff1a; 浏览器实现&#xff1a; 性和名输入&#xff1a; 只读输入&#xff1a; 读写输入&#xff1a; 侦听器属性watch 练习例子: 浏览器实现&#xff1a; 属性侦听&#xff1a; 对象侦听&#xff1a; 对象中的属性侦听&#xf…

基于STM32CUBEMX驱动TMOS模块STHS34PF80(2)----驱动STHS34PF80进行人体检测

基于STM32CUBEMX驱动TMOS模块STHS34PF80----2.驱动STHS34PF80进行人体检测 概述样品申请视频教程参考Demo引导温度测量滤波方式智能识别算法使用块数据更新&#xff08;BDU&#xff09;功能设置ODR速率状态寄存器main.c 概述 STHS34PF80 是一款非冷却、工厂校准的红外运动和存…

Java:异常处理:捕获异常,记录异常并响应合话的信息给用户;捕获异常,尝试重新修复

异常处理 1、埔获异常&#xff0c;记录异常并响应合话的信息给用户 public static void main(String[ ] args){ try {test1(); }catch (FileNotFoundException e) {system.out.println("您要找的文件不存在!! ");e.printstackTrace();//打印出这个异常对象的信息。记…

如何运用小程序技术闭环运营链路?

如何通过线上小程序获取用户线索&#xff0c;提高企业抗风险能力&#xff0c;建立有效的营销数字化系统一直是困扰每一个小程序开发者与运营者的问题。 当我们选择使用小程序设计自己的运营流程时&#xff0c;从「推广」到「转化」&#xff0c;再到最终的「留存」都是运营过程…

Grafana Loki

Loki是 Grafana Labs 团队最新的开源项目&#xff0c;是一个水平可扩展&#xff0c;高可用性&#xff0c;多租户的日志聚合系统。它的设计非常经济高效且易于操作&#xff0c;因为它不会为日志内容编制索引&#xff0c;而是为每个日志流编制一组标签。项目受 Prometheus 启发&a…

可组装的模块化开源掌机GameShell,组装起了万千极客的童年

对于热衷于复古游戏及开源掌机的极客玩家来说&#xff0c;开源硬件的普及&#xff0c;让更多极客可以有机会体验到亲手DIY掌机的乐趣&#xff0c;属于开源掌机的圈子也由此应运而生。 由一群复古游戏爱好者组成的Clockwork团队希望更进一步拓展开源掌机的拓展性和自定义性&…

AEM网络助手NSA升级更新-版本大更新

关注过或者使用AEM线缆认证测试的朋友&#xff0c;对于这款8类线认证测试仪不会陌生。 3.0-4.0是一个重大的版本变更&#xff0c;下面我们重点看看那些部分做了升级改动。 1&#xff0c;操作主界面部分&#xff0c;最大的变化的是&#xff0c;颜色对比度大为改动。界面更加协…

rabbitmq的消息应答

消费者完成一个任务可能需要一段时间&#xff0c;如果其中一个消费者处理一个长的任务并仅只完成 了部分突然它挂掉了&#xff0c;会发生什么情况。RabbitMQ 一旦向消费者传递了一条消息&#xff0c;便立即将该消 息标记为删除。在这种情况下&#xff0c;突然有个消费者挂掉了…

如何保证数据库的数据和Redis的数据一致性

实际项目中有可能会使用Redis缓存数据&#xff0c;那么在更新数据的时候如何保证数据库中的数据和Redis缓存的数据一致&#xff0c;缓存同步策略的选择是一个很重要的问题。网上有各种说法&#xff0c;大概总结有以下几种&#xff0c;看看每种方案是否可行以及存在的问题和适用…

思维导图模板下载网站有哪些?这6个网站优质模板任你选!

信息时代&#xff0c;有效的信息组织和知识管理变得尤其重要。思维导图&#xff0c;作为一种强大的视觉化工具&#xff0c;可以帮助我们整理和理解复杂的信息&#xff0c;提高工作和学习效率。 好的思维导图模板能帮助我们拓展思路、提升美观度、更快地完成思维导图的绘制。今…

【小梦C嘎嘎——启航篇】string介绍以及日常使用的接口演示

【小梦C嘎嘎——启航篇】string 使用&#x1f60e; 前言&#x1f64c;C语言中的字符串标准库中的string类string 比较常使用的接口对上述函数和其他函数的测试代码演示&#xff1a; 总结撒花&#x1f49e; &#x1f60e;博客昵称&#xff1a;博客小梦 &#x1f60a;最喜欢的座右…

好用的安卓手机投屏到mac分享

工具推荐&#xff1a;scrcpy github地址&#xff1a;https://github.com/Genymobile/scrcpy/tree/master mac使用方式 安装环境&#xff0c;打开terminal&#xff0c;执行以下命令&#xff0c;没有brew的先安装brew brew install scrcpy brew install android-platform-too…

Mybatis 源码 ① :开篇

文章目录 一、前言二、项目搭建三、自动装配四、总结 一、前言 Mybatis 官网 以及 本系列文章地址&#xff1a; Mybatis 源码 ① &#xff1a;开篇Mybatis 源码 ② &#xff1a;流程分析Mybatis 源码 ③ &#xff1a;SqlSessionMybatis 源码 ④ &#xff1a;TypeHandlerMybat…

ubuntu1804系统ROS1和ROS2一键装机

备忘一下ROS1和ROS2的一键装机 原网址:小鱼的一键安装系列 指令: wget http://fishros.com/install -O fishros && . fishros如果想同时安装ROS1和ROS2, 运行两次. fishros, 工具会自动将ROS1和ROS2放在不同的文件目录下 安装完每次打开终端时, 会提示选择ROS1还是RO…

【Linux】应用层协议

【Linux】应用层协议 文章目录 【Linux】应用层协议1、协议作用1.1 应用层需求1.2 协议分类 2、HTTP & HTTPS2.1 HTTP/HTTPS 简介2.2 HTTP工作原理2.3 HTTPS工作原理2.4 区别 3、URL3.1 编码解码3.2 URI & URL 4、HTTP 消息结构4.1 HTTP请求方法4.2 HTTP请求头信息 5、…