百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

SpringBoot系列(七):Java8的Stream API,让集合操作更为高效

bigegpt 2024-08-09 11:15 2 浏览

本文我们将开个小插曲,分享介绍如何基于Java8提供的Stream特性,高效操作我们的集合,如List、Set、Map等等。其中,将主要介绍Stream特性提供的筛选过滤功能Filter、对象转化功能Map、去重Distinct、排序Sorted、最小值Min以及最大值Max等核心操作。

了解过jdk动态的小伙伴们估计都知道,jdk已经出到12的版本了(是不是有点怀疑目前仍然还在使用jdk1.6、jdk1.5的自己),当然啦,我们都知道,不管jdk怎么升级,其底层核心数据库以及jvm的特性是变化不大的,特别是java8之后的版本,其主要还是以java8作为奠基进行一步步扩张的。如下图所示:

Java8对外提供的特性有很多,Stream便是其中的一大功能特性,除此之外,Java8还提供了接口默认方法、Lambda表达式、函数式接口等等。说起Java8的Stream,其在集合的操作中着实发挥了强大的作用,别的不说,其中的简洁、高效就特别令人眼前一亮。

Stream作为Java8的新特性,主要是基于lambda表达式,是对集合对象功能的增强,它专注于对集合对象进行各种高效、便利的聚合操作或者大批量的数据操作,可以提高编程的效率和代码可读性。

对于Stream的原理,正是其字面上的含义,Stream是将等待被处理的元素看做一种流,而流在管道中传输,并且可以在管道的节点上执行相应的处理操作,包括过滤筛选、去重、排序、聚合等等,元素流在管道中经过中间操作的处理,最后由最终操作如collect等方法得到前面处理的结果。

对于Stream的原理,各位小伙伴也可以网上搜索相应的文章进行深入的研究,在这里我们只做简单性的介绍。在后续的代码实战中,各位小伙伴可以看到上述对于Stream的原理将很好地在代码中得到体现。

值得一提的是,Stream API在执行的具体操作之前,需要先生成“流”,主要有两种方式:

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

parallelStream() - 为集合创建并行流

下面,我们在com.debug.springboot.server.dto目录下新建一个实体类PersonDto,用于后续的Stream代码实战中,其源代码如下所示:


@Data
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode
public class PersonDto implements Serializable{
 private Integer id;
 private Integer age;
 private String name;
}

其中,我们需要在该实体类中加入Equals()和HashCode()方法,用于后续执行Stream的去重API做铺垫!

另外,也需要在com.debug.springboot.server.utils 包目录下新建一个Java8Util类,用于介绍一些比较突出的Steam API操作。

首先,我们需要在Java8Util类中新建一个可以被共用的对象集合,并采用static静态代码块进行初始化,如下所示:


private static List<PersonDto> list;
 //初始化对象集合
 static {
 list= Lists.newLinkedList();
 PersonDto dto1=new PersonDto(1,21,"赵六");
 PersonDto dto2=new PersonDto(2,20,"张三");
 PersonDto dto3=new PersonDto(3,22,"李四");
 PersonDto dto4=new PersonDto(4,20,"王五");
 list.add(dto1);
 list.add(dto2);
 list.add(dto3);
 list.add(dto4);
 }

1、首先介绍Stream的筛选过滤功能Filter:下面的代码用于筛选过滤出年龄>20的对象集合,筛选过滤出名字为 王五 的对象信息,如下所示:


//筛选功能:filter 结合 collect方法 使用
 public static void method1(){
 //筛选年龄大于20的小伙子
 if (list!=null && !list.isEmpty()){
 System.out.println("\n--filter筛选功能1,结果:");
 List<PersonDto> resList=list.stream().filter(p -> p.getAge() > 20).collect(Collectors.toList());
 System.out.println(resList);
 }
 //筛选名字为 王五 的小伙子
 if (list!=null && !list.isEmpty()){
 System.out.println("\n--filter筛选功能2,结果:");
 List<PersonDto> resList=list.stream().filter(p -> "王五".equals(p.getName())).collect(Collectors.toList());
 System.out.println(resList);
 }
 }

之后,我们可以写一个main方法,直接调用method1(),其运行结果如下图所示:

2、紧接着,我们介绍Stream中的转换功能Map,如有以下的业务场景:当得到一个对象集合之后,要求我们需要抽取出每个对象中的某个字段,组成新的列表,比如抽取这个对象集合中的Id,或者Name,从而组成新的一个列表,源代码如下所示:


//转换map~按照指定的字段/元素属性进行转换:结合 collect 方法使用
 public static void method2(){
 if (list!=null && !list.isEmpty()){
 System.out.println("\n--转换map~按照指定的字段/元素属性进行转换,结果:");
 Set<String> nameSet=list.stream().map(PersonDto::getName).collect(Collectors.toSet());
 System.out.println(nameSet);
 }
 }

运行结果如下图所示:

3、然后,我们介绍一下“对象去重Distinct”的操作,这一操作,我们需要在实体类中加入 @EqualsAndHashCode 的lombok注解,源代码如下所示:


//去重distinct ~ 配合对象的 equals() 和 hashCode()方法
 public static void method3(){
 //TODO:对象去重 - 对象需要实现equals hashCode方法
 list.add(new PersonDto(4,20,"王五"));
 System.out.println("去重以前:"+list);
 List<PersonDto> resList=list.stream().distinct().collect(Collectors.toList());
 System.out.println("去重以后:"+resList);
 }

运行结果如下图所示:

4、顺道,我们介绍一下Stream提供的Sorted排序功能,即我们可以根据对象中的某个字段实施某种排序方式(正序、倒序)等,如下代码所示,我们可以借助Comparator比较器连续先后的对对象集合进行排序:先按照年龄排序、再按照id排序(正序、倒序),源代码如下所示:


//排序sorted
 public static void method4(){
 //按照年龄排序、再按照id排序
 list.add(new PersonDto(0,20,"郑六"));
 if (list!=null && !list.isEmpty()){
 List<PersonDto> resList=list.stream()
 .sorted(Comparator.comparingInt(PersonDto::getAge).thenComparing(Comparator.comparing(PersonDto::getId)))
 .collect(Collectors.toList());
 System.out.println("按照年龄排序、再按照id排序-顺序:\n"+resList);
 }
 //按照年龄排序、再按照id排序 ~ 也可以将最终结果倒序来
 if (list!=null && !list.isEmpty()){
 List<PersonDto> resList=list.stream()
 .sorted(Comparator.comparingInt(PersonDto::getAge).thenComparing(Comparator.comparing(PersonDto::getId)).reversed())
 .collect(Collectors.toList());
 System.out.println("\n按照年龄排序、再按照id排序-最终倒序:\n"+resList);
 }
 }

其运行结果如下图所示:

5、最后,我们介绍一下如果根据对象中某个字段的最大、最小,从而取出整个对象集合中该最小值字段、最大值字段对应的对象记录,源码如下所示:


//最小min、最大max
 public static void method5(){
 if (list!=null && !list.isEmpty()){
 PersonDto p=list.stream()
 .min(Comparator.comparingInt(PersonDto::getId))
 .get();
 System.out.println("\nid最小:"+p);
 }
 if (list!=null && !list.isEmpty()){
 PersonDto p=list.stream()
 .max(Comparator.comparingInt(PersonDto::getAge))
 .get();
 System.out.println("\n年龄最大:"+p);
 }
 }

其运行结果如下图所示:

至此,关于Java8Stream一些常用的操作API,我们已经介绍完毕了,当然啦,除了本文所介绍的一个常用的API操作之外,Stream特性提供的功能操作还远远不止于此,若有小伙伴对Java8的新功能特性感兴趣,可以关注公众号“程序员实战基地”,并回复“java8”,即可免费领取关于java8函数式编程的pdf电子书<Java 8函数式编程>

补充

1、本文涉及到的相关的源代码可以到此地址,check出来进行查看学习:

https://gitee.com/steadyjack/SpringBootTechnology

2、目前Debug已将本文所涉及的内容整理录制成视频教程,感兴趣的小伙伴可以前往观看学习:

http://www.fightjava.com/web/index/course/detail/5

3、关注一下Debug的技术微信公众号呗,最新的技术文章、技术课程以及技术专栏将会第一时间在公众号发布哦!

推荐阅读:

SpringBoot系列(一):如何构建一个标准的Spring Boot项目

SpringBoot系列(二):如何构建统一的消息响应模型

SpringBoot系列(三):不要告诉我你还不会使用IDEA热部署功能

SpringBoot系列(四):SpringBoot整合Mybatis实现不一样的CRUD

SpringBoot系列(五):SpringBoot整合Mybatis实现多表关联查询

相关推荐

10w qps缓存数据库——Redis(redis缓存调优)

一、Redis数据库介绍:Redis:非关系型缓存数据库nosql:非关系型数据库没有表,没有表与表之间的关系,更不存在外键存储数据的形式为key:values的形式c语言写的服务(监听端口),用来存...

Redis系列专题4--Redis配置参数详解

本文基于windowsX64,3.2.100版本讲解,不同版本默认配置参数不同在Redis中,Redis的根目录中有一个配置文件(redis.conf,windows下为redis.windows....

开源一夏 | 23 张图,4500 字从入门到精通解释 Redis

redis是目前出场率最高的NoSQL数据库,同时也是一个开源的数据结构存储系统,在缓存、数据库、消息处理等场景使用的非常多,本文瑞哥就带着大家用一篇文章入门这个强大的开源数据库——Redis。...

redis的简单与集群搭建(redis建立集群)

Redis是什么?是开源免费用c语言编写的单线程高性能的(key-value形式)内存数据库,基于内存运行并支持持久化的nosql数据库作用主要用来做缓存,单不仅仅是做缓存,比如:redis的计数器生...

推荐几个好用Redis图形化客户端工具

RedisPlushttps://gitee.com/MaxBill/RedisPlusRedisPlus是为Redis可视化管理开发的一款开源免费的桌面客户端软件,支持Windows、Linux...

关于Redis在windows上运行及fork函数问题

Redis在将数据库进行持久化操作时,需要fork一个进程,但是windows并不支持fork,导致在持久化操作期间,Redis必须阻塞所有的客户端直至持久化操作完成。微软的一些工程师花费时间在解决在...

你必须懂的Redis十大应用场景(redis常见应用场景)

Redis作为一款高性能的键值存储数据库,在互联网业务中有着广泛的应用。今天,我们就来详细盘点一下Redis的十大常用业务场景,并附上Golang的示例代码和简图,帮助大家更好地理解和应用Redis。...

极简Redis配置(redis的配置)

一、概述Redis的配置文件位于Redis安装目录下,文件名为redis.conf(Windows名为redis.windows.conf,linux下的是redis.conf)你可以通过C...

什么是redis,怎么启动及如何压测

从今天起咱们一起来学习一下关于“redis监控与调优”的内容。一、Redis介绍Redis是一种高级key-value数据库。它跟memcached类似,不过数据可以持久化,而且支持的数据类型很丰富。...

一款全新Redis UI可视化管理工具,支持WebUI和桌面——P3X Redis UI

介绍P3XRedisUI这是一个非常实用的RedisGUI,提供响应式WebUI访问或作为桌面应用程序使用,桌面端是跨平台的,而且完美支持中文界面。Githubhttps://github....

windows系统的服务器快速部署java项目环境地址

1、mysql:https://dev.mysql.com/downloads/mysql/(msi安装包)2、redis:https://github.com/tporadowski/redis/r...

window11 下 redis 下载与安装(windows安装redis客户端)

#热爱编程是一种怎样的体验#window11下redis下载与安装1)各个版本redis下载(windows)https://github.com/MicrosoftArchive/r...

一款轻量级的Redis客户端工具,贼好用!

使用命令行来操作Redis是一件非常麻烦的事情,我们一般会选用客户端工具来操作Redis。今天给大家分享一款好用的Redis客户端工具TinyRDM,它的界面清新又优雅,希望对大家有所帮助!简介Ti...

一个.NET开发且功能强大的Windows远程控制系统

我们致力于探索、分享和推荐最新的实用技术栈、开源项目、框架和实用工具。每天都有新鲜的开源资讯等待你的发现!项目介绍SiMayRemoteMonitorOS是一个基于Windows的远程控制系统,完...

Redis客户端工具详解(4款主流工具)

大家好,我是mikechen。Redis是大型架构的基石,也是大厂最爱考察内容,今天就给大家重点详解4款Redis工具@mikechen本篇已收于mikechen原创超30万字《阿里架构师进阶专题合集...