一 引言

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 转载请注明来源

Stream流处理快速上手最佳实践的更多相关文章

  1. 5万字长文:Stream和Lambda表达式最佳实践-附PDF下载

    目录 1. Streams简介 1.1 创建Stream 1.2 Streams多线程 1.3 Stream的基本操作 Matching Filtering Mapping FlatMap Reduc ...

  2. Java8 Stream 的最佳实践

    Java8 Stream 的最佳实践 java8stream提供了对于集合类的流失处理,其具有以下特点: Lazy Evaluation(长度可以无限) 只能使用一次 内部迭代 Lazy Evalua ...

  3. [J2EE:中间件]LOG4J+Slf4J快速入门及日志最佳实践

    1 概述 1.1 常见的Java日志框架及选择 commons-logging和slf4j(slf4j-api.jar)都是日志类库的接口,供客户端使用,而没有提供实现! log4j,logback等 ...

  4. 快速web开发中的前后端框架选型最佳实践

    这个最佳实践是我目前人在做的一个站点,主要功能: oauth登录 发布文章(我称为"片段"),片段可以自定义一些和内容有关的指标,如“文中人物:12”.支持自定义排版.插图.建立相 ...

  5. Atitit. Gui控件and面板----程序快速启动区--最佳实践Launchy ObjectDock-o0g

    Atitit.  Gui控件and面板----程序快速启动区--最佳实践Launchy ObjectDock-o0g 两个方式::: 键盘式::先用热键呼叫出QS,然后开始输入程序中的部分字母,按En ...

  6. springboot + aop + Lua分布式限流的最佳实践

    整理了一些Java方面的架构.面试资料(微服务.集群.分布式.中间件等),有需要的小伙伴可以关注公众号[程序员内点事],无套路自行领取 一.什么是限流?为什么要限流? 不知道大家有没有做过帝都的地铁, ...

  7. 几个小实践带你快速上手MindSpore

    摘要:本文将带大家通过几个小实践快速上手MindSpore,其中包括MindSpore端边云统一格式及华为智慧终端背后的黑科技. MindSpore介绍 MindSpore是一种适用于端边云场景的新型 ...

  8. SpringBoot快速开发REST服务最佳实践

    一.为什么选择SpringBoot Spring Boot是由Pivotal团队提供的全新框架,被很多业内资深人士认为是可能改变游戏规则的新项目.早期我们搭建一个SSH或者Spring Web应用,需 ...

  9. KubeEdge快速上手与社区贡献实践

    1.KubeEdge的架构特点与优势 持久化 云端组件,EdgeController,设备抽象API,CSI Driver,Admission WebHook 边缘组件,EdgeHub,MetaMan ...

  10. Sentry 后端监控 - 最佳实践(官方教程)

    系列 1 分钟快速使用 Docker 上手最新版 Sentry-CLI - 创建版本 快速使用 Docker 上手 Sentry-CLI - 30 秒上手 Source Maps Sentry For ...

随机推荐

  1. AI开发效率低,你可以试试华为NAIE AutoML

    摘要:为解决AI工程师在开发AI应用场景所遇到的问题,NAIE平台落地AutoML框架(工具)来辅助大家更高效.更迅速解决AI开发问题. 你是不是还在为掌握的AI算法少而烦恼? 你是不是还在为选择某个 ...

  2. ModelArts的雪中送炭,让我拿下CCF BDCI华为Severless工作负载预测亚军

    摘要: 中国计算机学会大数据与计算智能大赛(CCF BDCI)华为Severless工作负载预测亚军方案和ModelArts使用体验分享 本文分享自华为云社区<免费薅ModelArts算力资源- ...

  3. Python图像处理丨图像缩放、旋转、翻转与图像平移

    摘要:本篇文章主要讲解Python调用OpenCV实现图像位移操作.旋转和翻转效果,包括四部分知识:图像缩放.图像旋转.图像翻转.图像平移. 本文分享自华为云社区<[Python图像处理] 六. ...

  4. 带你聚焦GaussDB(DWS)存储时游标使用

    摘要:游标是一种数据处理方法,提供了在查询结果集中进行逐行遍历浏览数据的方法,也可以将游标当做上下文区域的句柄或者指针,借助游标对指定位置的数据进行查询与处理. 本文分享自华为云社区<Gauss ...

  5. API 设计最佳实践(简版)

    Restful API 本文简称API,是一个种面向资源的架构.在Restful中一个API对应一个资源,资源可以是文本,图片,视频等.API特征有如下: 每一个URI代表一种资源 客户端和服务器之间 ...

  6. 6行代码!用Python将PDF转为word

    pdf转word应该算是一个很常见的需求了 网上有些免费的转换工具,一方面不安全,有文件泄露风险,另一方面有免费转换的次数限制. 今天向大家分享一个很好用的工具:pdf2docx 安装 $ pip i ...

  7. 批量上传 jar 包到远程 maven 仓库

    mvn deploy命令: mvn deploy:deploy-file -Dmaven.test.skip=true -Dfile=log-lib-1.1.jar -DgroupId=com.sun ...

  8. 《机器学习实战》 | 第3章 决策树(含Matplotlib模块介绍)

    系列文章:<机器学习实战>学习笔记 本篇文章使用到的完整代码:Here 决策树 优点:计算复杂度不高,输出结果易于理解,对中间值的缺失不敏感,可以处理不相关特征数据. 缺点:可能会产生过度 ...

  9. 【每日一题】21.边的染色 (DFS连通图 + 思维)

    补题链接:Here 思维不够,看到这种陌生的题目无从下手. 这题应该做过一次的人会觉得它其实并不难. 主要思想:把边权->点权. 这样做的好处是,无论你怎么分配点权,在环内的异或值一定为 \(0 ...

  10. AtCoder Beginner Contest 197(Sponsored by Panasonic) Person Editorial

    A - Rotate 先输出第二和第三个字符,然后再输出第一个字符即可 B - Visibility 以 \((x,y)\) 作为起点向4个方向探索不是 # 的点,注意一下会在\((x,y)\)重复计 ...