Stream流处理快速上手最佳实践 | 京东物流技术团队

news2024/11/16 7:54:21

一 引言

JAVA1.8得益于Lambda所带来的函数式编程,引入了一个全新的Stream流概念Stream流式思想类似于工厂车间的“生产流水线”,Stream流不是一种数据结构,不保存数据,而是对数据进行加工处理。Stream可以看作是流水线上的一个工序。在流水线上,通过多个工序让一个原材料加工成一个商品。

二 常用方法介绍

2.1 获取Stream流

所有的 Collection 集合都可以通过 stream 默认方法获取流;

java.util.Collection 接口中加入了default方法 stream 用来获取流,所以其所有实现类均可获取流。

ArrayList<XyBug> xyBugList = new ArrayList();
Stream<XyBug> stream = xyBugList.stream();


Stream 接口的静态方法 of 可以获取数组对应的流。

//String
Stream<String> stream = Stream.of("aa", "bb", "cc");
//数组
String[] arr = {"aa", "bb", "cc"};
Stream<String> stream7 = Stream.of(arr);
Integer[] arr2 = {11, 22, 33};
Stream<Integer> stream8 = Stream.of(arr2);
//对象
XyBug xyBug1 = new XyBug();
XyBug xyBug2 = new XyBug();
XyBug xyBug3 = new XyBug();
Stream<XyBug> bugStream = Stream.of(xyBug1, xyBug2, xyBug3);



2.2 Stream 数据处理常用方法

forEach方法

该方法接收一个 Consumer 接口函数,会将每一个流元素交给该函数进行处理

List<String> list = new ArrayList<>();
Collections.addAll(list, "str1", "str2", "str3", "str4", "str5", "str6");
list.stream().forEach((String s) -> {
  System.out.println(s);
  });
//简写
list.stream().forEach(s -> System.out.println(s));


s代表list中的每一个元素,流式处理依次遍历每个元素

->后的代码为每个元素处理逻辑

count方法

count 方法来统计其中的元素个数,返回值为long类型

long count = list.stream().count();


distinct方法

对流中的数据进行去重操作,普通类型可直接去重

//将22、33重复数据去除
Stream.of(22, 33, 22, 11, 33).distinct().collect(Collectors.toList());


自定义类型是根据对象的hashCode和equals来去除重复元素的

XyBug实体类中加@Data注解,hashCode和equals会别重写,在使用distinct方法时判断去重

ArrayList bugList = JSON.parseObject(bugs, ArrayList.class);
ArrayList<XyBug> xyBugList = new ArrayList();
List collect = (List) bugList.stream().distinct().collect(Collectors.toList());


通过distinct()方法去重,去重后的数据通过collect(Collectors.toList())组成新6的list

limit方法

方法可以对流进行截取,只取用前n个,参数是一个long型,如果集合当前长度大于参数则进行截取。否则不进行操作

List<String> list = new ArrayList<>();
Collections.addAll(list, "1", "2", "3", "4", "5", "6");
List<String> collect = list.stream().limit(3).collect(Collectors.toList());


将前3个String对象截取,组成新的list

skip方法

如果希望跳过前几个元素,可以使用 skip 方法获取一个截取之后的新流,如果流的当前长度大于n,则跳过前n个;否则将会得到一个长度为0的空流

List<String> list = new ArrayList<>();
Collections.addAll(list, "1", "2", "3", "4", "5", "6");
List<String> collect = list.stream().skip(3).collect(Collectors.toList());


跳过前3个String对象,后三个组成新的list

filter方法

filter用于过滤数据,返回符合过滤条件的数据,可以通过 filter 方法将一个流转换成另一个子集流,该接口接收一个 Predicate 函数式接口参数(可以是一个Lambda或方法引用)作为筛选条件

List<String> list = new ArrayList<>();
Collections.addAll(list, "1", "22", "3", "4", "55", "6");
//filter方法中写入筛选条件,将过滤后的数据组成新的list
list.stream().filter(s -> s.length() == 2).collect(Collectors.toList());


通过该条语句s -> s.length() == 2,筛选出22、55

map方法

将流中的元素映射到另一个流中,可以将当前流中的T类型数据转换为另一种R类型的流

List<PersonCrDto> laputaCrDtos = queryListLaputaByBeginEndTime(begin, end);
//将list中的PersonCrDto对象的userName属性取到,收集成set集合
laputaCrDtos.stream().map(PersonCrDto::getUserName).collect(Collectors.toSet())


将list中的每个对象的userName数据拿到,组成Set集合

stream分组

List<XyBug> list = new ArrayList<>();
Map<String, List<XyBug>> collect = list.stream().collect(Collectors.groupingBy(XyBug::getBugType));


根据bug类型进行分组,分组后会组成map,key是组名,value是组下的数据

stream排序

sort(),默认正序排列,加入reversed()方法后倒叙排列

List<XyBug> list = new ArrayList<>();
//根据createTime正序排列
List<XyBug> collect = list.stream().sorted(Comparator.comparing(XyBug::getCreateTime)).collect(Collectors.toList());
//根据createTime倒叙排列
List<XyBug> collect = list.stream().sorted(Comparator.comparing(XyBug::getCreateTime).reversed()).collect(Collectors.toList());



collect方法

将处理后数据收集为list,collect(Collectors.toList())

将处理后数据收集为set,collect(Collectors.toSet())

根据某个字段值将数据分组map,collect(Collectors.groupingBy(o -> o.value())))

三 实践举例

需求:将bug数据通过orgTierName分组,存储到map中

未使用Stream,需要使用for循环并且进行各种判断,代码行数较多

HashMap<String, List<XyBug>> map = new HashMap<>();
for (XyBug one : bugList){
    if(one.getOrgTierName() != null){
        if(map.get(one.getOrgTierName()) == null){
            List<XyBug> list = new ArrayList();
            list.add(one);
            map.put(one.getOrgTierName(),list);
        }else {
            map.get(one.getOrgTierName()).add(one);
        }
    }
}


使用Stream,一行代码搞定,直观并高效

collectDeptBugMap = bugList.stream().filter(o -> o.getOrgTierName() != null).collect(Collectors.groupingBy(o -> o.getOrgTierName()));


四 总结

Stream是对集合(Collection)对象功能的增强,能对集合对象进行各种非常便利、高效的聚合操作,或者大批量数据操作,提高编程效率、简洁性和程序可读性。本文通过简单举例,希望帮助读者快速上手使用流处理,Stream流处理功能非常强全,更多方法请参考API文档。

作者:京东物流 杨靖平

来源:京东云开发者社区  自猿其说Tech 转载请注明来源

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

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

相关文章

深度解析NLP文本摘要技术:定义、应用与PyTorch实战

目录 1. 概述1.1 什么是文本摘要&#xff1f;1.2 为什么需要文本摘要&#xff1f; 2. 发展历程2.1 早期技术2.2 统计方法的崛起2.3 深度学习的应用2.4 文本摘要的演变趋势 3. 主要任务3.1 单文档摘要3.2 多文档摘要3.3 信息性摘要 vs. 背景摘要3.4 实时摘要 4. 主要类型4.1 抽取…

【Linux进行时】进程状态

进程状态&#xff1a; ❓假设我们在上课&#xff0c;在B站上上课&#xff0c;请问我们的B站是不是一直运行呢&#xff1f;&#x1f4a1;不是的&#xff01; ❓假设我们同时打开了B站和PDF阅读器时&#xff0c;是怎么运行的呢&#xff1f; &#x1f4a1;每一个进程在CPU跑一会&a…

Layui快速入门之第十三节 日期与时间选择器

目录 一&#xff1a;基本用法 API 渲染 属性 弹出提示 2.8 获取实例 2.8 解除实例绑定 2.8 关闭日期面板 2.7 获取某月的最后一天 二&#xff1a;常规用法 三&#xff1a;多类型选择器 四&#xff1a;范围选择 五&#xff1a;直接静态显示 六&#xff1a;更多功能…

Vue入门--vue的生命周期

一.什么是Vue 二.Vue的简介 官方网址 特点 三. 前后端的分离 重大问题 优势 4.Vue入门 定义一个管理边界 ​编辑 测试结果 vue的优势 ​编辑 测试结果 5.Vue的生命周期 vue的生命周期图 ​编辑建立一个html 测试结果 一.什么是Vue Vue是一种流行的JavaScript前端框…

华为云云耀云服务器L实例评测|使用宝塔10分钟部署一个围猫猫小游戏

目录 前言一、选择华为云云耀云服务器L实例的原因二、华为云云耀云服务器的优势三、快速部署一个小游戏&#xff08;1&#xff09;终端部署1、使用Termius工具连接终端2、安装Nginx3、上传打包文件 &#xff08;2&#xff09;宝塔可视化面板部署1、进入宝塔2、宝塔菜单3、上传代…

【实训项目】你好,教练-校园私教平台的设计与开发

1.设计摘要 随着社会的进步&#xff0c;人们的健康意识逐渐提高&#xff0c;越来越多的人选择在闲暇时间健身&#xff0c;在大学生群体中&#xff0c;这一现象犹为明显。在大学城内&#xff0c;有多家健身房供同学选择&#xff0c;也有许多同学选择在操场或者宿舍内自己健身&a…

使用Seata实现分布式事务

Seata 一&#xff1a;故事背景二&#xff1a;使用方法2.1 下载安装Seata2.4 修改对应配置文件。2.4.1 配置中心2.4.1 注册中心2.4.2 日志保存模式 2.3 启动Seata2.4 项目中集成2.5 数据库内新建undo_log 表进行日志记录2.6 编写代码测试Seata提供的分布式事务功能 三&#xff1…

带你熟练使用list

&#x1f388;个人主页:&#x1f388; :✨✨✨初阶牛✨✨✨ &#x1f43b;强烈推荐优质专栏: &#x1f354;&#x1f35f;&#x1f32f;C的世界(持续更新中) &#x1f43b;推荐专栏1: &#x1f354;&#x1f35f;&#x1f32f;C语言初阶 &#x1f43b;推荐专栏2: &#x1f354;…

EdgeX Foundry MQTT设备服务

一、部署edgex 1.运行命令行&#xff0c;进入放置docker-compose-fuji-no-secty.yml文件的路径下 下载到本地的docker-compose文件 执行&#xff1a; docker-compose -f docker-compose-fuji-no-secty.yml pull 拉取相关镜像&#xff0c;这里默认将文件中没有注释的服务镜像全部…

企业注册版 :ag-Grid Enterprise 30.1.0

Ag-Grid 被描述为一种商业产品&#xff0c;已根据 EULA 进行分发&#xff0c;并受到我们提供的技术团队的鼓励。它非常高级&#xff0c;具有与行分组一样的性能以及范围选择、主数据和案例、行的服务器端模型等等。Ag-Grid Enterprise 通常附带集成图表&#xff0c;允许用户和开…

无涯教程-JavaScript - IFS函数

描述 IFS函数检查是否满足一个或多个条件,并返回与第一个TRUE条件相对应的值。此功能已在Excel 2016中添加。 语法 IFS (logical_test1, value_if_true1, [logical_test2, value_if_true2], [logical_test3, value_if_true3]…) 争论 Argument描述Required/Optionallogical…

无涯教程-JavaScript - ATAN函数

描述 The ATAN function returns the arctangent, or inverse tangent, of a number. The returned angle is given in radians between -π/2 and π/2. The arctangent is the angle whose tangent is number. 语法 ATAN (number)争论 Argument描述Required/OptionalNumb…

springboot配置注入增强(二)属性注入的原理

一 原理 1 配置的存储 springboot在启动的时候会后构建一个org.springframework.core.env.Environment类型的对象&#xff0c;这个对象就是用于存储配置&#xff0c;如图springboot会在启动的最开始创建一个Environment对象 这个webApplicationType的枚举是在new SpringAppli…

Learn Prompt-Midjourney 图片生成

简介 随着 ChatGPT 的爆火&#xff0c;越来越多的人开始关注并尝试 AI 相关的应用。而图片生成就是其中一个备受瞩目的领域。目前已经有许多图像生成工具&#xff0c;如 Midjourney&#xff0c;Stable Diffusion&#xff0c;DALL-E&#xff0c;Firefly等。本课程主要是以 Midj…

Python 变量的类型注解

视频版教程 Python3零基础7天入门实战视频教程 类型注解 前面有个示例&#xff0c;我们函数参数是字符串类型&#xff0c;但是pycharm工具不知道&#xff0c;所以不会给我们提示s的方法&#xff0c;我们只能人工手写&#xff0c;效率大大降低。 类型注解&#xff1a; 在代码中…

心法利器[101] | 从大模型到大模型系统

心法利器 本栏目主要和大家一起讨论近期自己学习的心得和体会&#xff0c;与大家一起成长。具体介绍&#xff1a;仓颉专项&#xff1a;飞机大炮我都会&#xff0c;利器心法我还有。 2022年新一版的文章合集已经发布&#xff0c;累计已经60w字了&#xff0c;获取方式看这里&…

使用ElementPlus实现内嵌表格和内嵌分页

前言 有时遇到这样的需求&#xff0c;就是在表格里面嵌入一个表格&#xff0c;以及要求带有分页&#xff0c;这样在ElementPlus中很好实现。以下使用Vue2语法实现一个简单例子&#xff0c;毕竟Vue3兼容Vue2语法&#xff0c;若想要Vue3版本例子&#xff0c;简单改改就OK了。 一…

数据结构——图的应用

文章目录 前言一、图的应用1. 最小生成树普里姆&#xff08;Prim&#xff09;算法克鲁斯卡尔&#xff08;Kruskal&#xff09;算法 2. 最短路径Dijkstra算法求单源最短路径 3. 拓扑结构4. 关键路径 总结 前言 图的应用 1.1 最小生成树 1.2 最短路径 1.3 拓扑结构 1.4 关键路径…

【网络教程】揭秘Windows SSH服务端免密登录:告别繁琐,享受安全连接

文章目录 开启Windows下的SSH服务端图形界面安装手动下载安装Windows如何查看系统用户名Windows如何查看本机IP开启免密登录Window生成秘钥Linux下生成秘钥配置公钥视频讲解开启Windows下的SSH服务端 这篇文章演示的环境是Windows11Windows的SSH服务端默认情况下是没有安装的,…

9.项目细节调整

文章目录 学习资料项目整体细节调整处理首页 学习资料 https://www.bilibili.com/video/BV13g411Y7GS/?p24&spm_id_frompageDriver&vd_sourceed09a620bf87401694f763818a31c91e 项目整体细节调整 处理首页 默认的首页 肯定不能给人看。文件在这个位置。 可以删除…