在日常开发使用中,运用循环迭代(for,forEach)的方式进行一些数据处理,
或者直接用sql语句进行数据处理是非常常见的事情,
例如排序(sorted),过滤(filter),映射(map),分组(groupingBy)等等一系列操作。
在Java8 Collectors.toMap的坑此话题下,讨论的都是jdk1.8的特性stream对日常开发带来的便利和好处,关于stream有下图的一个概述
什么是Stream
?
Stream
将要处理的元素集合看作一种流,在流的过程中,借助Stream API
对流中的元素进行操作,比如:筛选、排序、聚合等
今天想记录的不是怎么去全面的学习stream的开发规范和每个细节,
而在我日常使用中,最常使用到的几个特性。
为了保证代码的易读性,同时也避免在遍历中出现特殊逻辑的bug,
使用stream有助于我们节省开发时间,提升开发效率,并有强阅读性的优势
在性能上,除非服务器是单核,且代码片段非常小,遍历次数非常小的情况,不推荐使用stream,
其他状态下,使用stream不会对性能造成影响
接下来,我就实际讲讲是怎么使用的。
1.开发中,有个逻辑是“只有“未”和“失败”状态的任务才可以进行“操作”
在此基础上,我们就可以使用stream的filter结合Lambda对数据进行过滤,
而不用去在sql中使用 where status in (...,...) 的操作,或使用StrUtil进行条件判断
相对来说,这样的代码,看上去也更简便一些
相似的,我们可以灵活运用于这个场景
所以,在需要进行过滤判断,或者单纯的需要过滤数据的时候,都可以使用stream来更方便的进行数据操作,
更多的使用方式先不提了,可以组合进行尝试。
2.在使用过程中,我们也会有关联表查询的这样一些操作,不知道大家平时怎么玩,
如果我不使用stream,有两种方式,一种是写视图,联合查询,
因为jpa在复杂数据库逻辑查询(多表、联合)下,随着表关系和表字段的迭代, Spring Data JPA 查询的效率和优化比 Mybatis 困难得多,
另一种就是自己加个list,或者map,写for循环进行累加关联字段的值,然后再将此list作为查询条件,进入子表的查询
使用stream,就是在第二种方法的基础上,减少了循环和赋值,使用stream本身获取关联字段的list或set,如下图
这样一行代码便解决了开发过程中比较麻烦费时间的代码问题,这是用到了stream的映射(map)和聚合(collect),在这里,有个特殊的地方也要进行说明
stream的推荐写法如下
List jlTemplateIds = entities.stream().map(entity -> entity.getId()).collect(Collectors.toList());
但是代码中的写法是
List<String> jlTemplateIds = taxDeclareEntities.stream().map(TEntity::getId).collect(Collectors.toList());
这样写的原因是sonar的异味排错中给了这种提示
所以在使用过程中,如果有同事碰到这个问题,可以参考解决
3.我们还会遇到这样的问题,为了系统的性能,我们必须杜绝循环查库等一系列不规范的操作,
但是不可能每次查询都刚好是自己想要的数据,一次性查出的数据总归是要进行筛选和遍历的,
还是使用建list或set或map加for循环的方式,这样的方式易读体验实在不佳,而且会占用更多的开发思维,
如果使用stream进行分组筛选,而后进行过滤遍历的话,代码将会更易阅读一些,同时也会减少时间,空间复杂度
具体的业务逻辑不做复述,但是stream在我实际开发中,确实给了我很大的帮助
此次记录一是为了这个特性,我觉得可以推荐出来给大家多了解多用
另一个原因是,我记录了以后,对它的理解也更深了一点,之前只用到了过滤,映射和聚合,还有相当一部分的功能还未使用到
经过积累和学习之后,可以更方便的使用stream
祝工作顺利
以上