Java 8:Stream API 流式操作

简介: Java 8:Stream API 流式操作


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 作为参数,用于指定查询条件
  • new QueryWrapper<SystemApplicationType>().orderByAsc(SystemApplicationTypeCol.ID):这是创建一个查询条件对象的过程;QueryWrapper 是 MyBatis-Plus 提供的用于构建查询条件的工具;orderByAsc(SystemApplicationTypeCol.ID) 表示按照 SystemApplicationType 实体类中 ID 字段的升序进行排序。
  • .stream():这将查询结果转换为一个 Stream 对象,便于后续的操作
  • .map(bean -> new ResCommonIdNameCode(bean.getId(), bean.getName(), bean.getName())):这部分使用 map 操作将查询结果的每个 SystemApplicationType 对象映射为 ResCommonIdNameCode 对象;ResCommonIdNameCode 是一个自定义的类,构造函数接受 id、name 和 code 作为参数,用于创建一个新的对象
  • .collect(Collectors.toList()):最后,使用 collect 方法将 Stream 对象收集为 List,即最终的结果列表
noticeResponses.stream()
                .sorted(Comparator.comparing(SystemNoticeResponse::getReadStatus)
                        .thenComparing(Comparator.comparing(SystemNoticeResponse::getCreateAt).reversed()))
                .collect(Collectors.toList());

.stream():将 noticeResponses 列表转换为一个 Stream 对象,使其能够使用 Stream API 提供的操作

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

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


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


目录
相关文章
|
9天前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
35 2
|
17天前
|
缓存 监控 Java
如何运用JAVA开发API接口?
本文详细介绍了如何使用Java开发API接口,涵盖创建、实现、测试和部署接口的关键步骤。同时,讨论了接口的安全性设计和设计原则,帮助开发者构建高效、安全、易于维护的API接口。
44 4
|
25天前
|
Java API 数据处理
探索Java中的Lambda表达式与Stream API
【10月更文挑战第22天】 在Java编程中,Lambda表达式和Stream API是两个强大的功能,它们极大地简化了代码的编写和提高了开发效率。本文将深入探讨这两个概念的基本用法、优势以及在实际项目中的应用案例,帮助读者更好地理解和运用这些现代Java特性。
|
1月前
|
Java 大数据 API
别死脑筋,赶紧学起来!Java之Steam() API 常用方法使用,让开发简单起来!
分享Java Stream API的常用方法,让开发更简单。涵盖filter、map、sorted等操作,提高代码效率与可读性。关注公众号,了解更多技术内容。
|
1月前
|
存储 Java API
如何使用 Java 中的 API 更改 PDF 纸张大小
如何使用 Java 中的 API 更改 PDF 纸张大小
50 11
|
1月前
|
机器学习/深度学习 算法 Java
通过 Java Vector API 利用 SIMD 的强大功能
通过 Java Vector API 利用 SIMD 的强大功能
44 10
|
1月前
|
分布式计算 Java 大数据
大数据-147 Apache Kudu 常用 Java API 增删改查
大数据-147 Apache Kudu 常用 Java API 增删改查
33 1
|
2月前
|
安全 Java API
时间日期API(Date,SimpleDateFormat,Calendar)+java8新增日期API (LocalTime,LocalDate,LocalDateTime)
这篇文章介绍了Java中处理日期和时间的API,包括旧的日期API(Date、SimpleDateFormat、Calendar)和Java 8引入的新日期API(LocalTime、LocalDate、LocalDateTime)。文章详细解释了这些类/接口的方法和用途,并通过代码示例展示了如何使用它们。此外,还讨论了新旧API的区别,新API的不可变性和线程安全性,以及它们提供的操作日期时间的灵活性和简洁性。
|
1月前
|
SQL Java API
深入探索Java的持久化技术——JPA(Java Persistence API)
【10月更文挑战第10天】深入探索Java的持久化技术——JPA(Java Persistence API)
35 0
|
1月前
|
Java API 数据库
深入探索Java的持久化技术——JPA(Java Persistence API)
【10月更文挑战第10天】深入探索Java的持久化技术——JPA(Java Persistence API)
44 0
下一篇
无影云桌面