当前位置: 首页 > news >正文

Java Stream 流式编程

Java 8 引入的 Stream API 是一种 声明式 的数据处理方式,用于处理集合、数组等数据源。它将数据处理操作(如过滤、映射、排序、聚合)以链式方式组织,简化了集合的处理逻辑,提升了代码的可读性和可维护性。


一、Stream 的核心概念

1. 流(Stream)

  • 流是一组元素的序列,支持顺序或并行处理。
  • 流不是集合,它本身不存储数据,而是对数据源(如 ListSetMap、数组等)进行操作。
  • 流只能被消费一次,一旦执行终端操作,流就关闭,不能再使用。

2. 操作类型

Stream 的操作分为两类:

操作类型说明常见方法
中间操作(Intermediate Operations)返回一个新的流,可以链式调用filter()map()sorted()distinct()
终端操作(Terminal Operations)返回非流的结果(如 Listintvoidcollect()forEach()count()findFirst()

二、Stream 的处理流程

List<String> result = list.stream()
.filter(s -> s.length() > 3)// 中间操作
.map(String::toUpperCase)// 中间操作
.sorted()// 中间操作
.collect(Collectors.toList());// 终端操作

流程图:

数据源(如 List) → 流 → 中间操作 → 中间操作 → ... → 终端操作 → 结果

三、常用操作与案例

1. 创建流(Stream)

// 从集合创建
List<String> list = Arrays.asList("a", "b", "c");
Stream<String> stream = list.stream();// 从数组创建
String[] arr = {"x", "y", "z"};
Stream<String> stream2 = Arrays.stream(arr);// 生成无限流
Stream<Integer> infiniteStream = Stream.iterate(1, n -> n + 1);

2. 中间操作

(1) filter(Predicate):过滤符合条件的元素
List<String> filtered = list.stream()
.filter(s -> s.length() > 3)
.collect(Collectors.toList());
(2) map(Function):将元素映射为其他类型
List<Integer> lengths = list.stream()
.map(String::length)
.collect(Collectors.toList());
(3) sorted(Comparator):排序
List<String> sorted = list.stream()
.sorted(Comparator.reverseOrder()) // 降序
.collect(Collectors.toList());
(4) distinct():去重
List<String> unique = list.stream()
.distinct()
.collect(Collectors.toList());
(5) limit(long) / skip(long):截取或跳过
List<String> limited = list.stream()
.limit(2) // 取前2个元素
.collect(Collectors.toList());

3. 终端操作

(1) collect(Collector):收集结果(最常用)
List<String> listResult = stream.collect(Collectors.toList());
Set<String> setResult = stream.collect(Collectors.toSet());
Map<String, Integer> mapResult = stream.collect(Collectors.toMap(...));
(2) forEach(Consumer):遍历
stream.forEach(System.out::println);
(3) count():统计元素数量
long count = stream.count();
(4) findFirst() / findAny():查找第一个或任意元素
Optional<String> first = stream.findFirst();
(5) anyMatch() / allMatch() / noneMatch():匹配判断
boolean hasLong = stream.anyMatch(s -> s.length() > 3);
(6) reduce():归约操作(如求和、最大值)
int sum = stream.mapToInt(Integer::intValue).sum();
Optional<Integer> max = stream.reduce(Integer::max);

四、高级用法与案例

1. 分组(Grouping By)

Map<String, List<User>> usersByGender = userList.stream()
.collect(Collectors.groupingBy(User::getGender));

2. 分区(Partitioning By)

Map<Boolean, List<User>> activeUsers = userList.stream()
.collect(Collectors.partitioningBy(User::isActive));

3. 统计(Summarizing)

IntSummaryStatistics stats = userList.stream()
.collect(Collectors.summarizingInt(User::getAge));

4. 多级分组

Map<String, Map<String, List<User>>> usersByGenderAndCity = userList.stream()
.collect(Collectors.groupingBy(User::getGender,
Collectors.groupingBy(User::getCity)));

5. 拼接字符串(Joining)

String names = userList.stream()
.map(User::getName)
.collect(Collectors.joining(", ")); // "Alice, Bob, Charlie"

五、并行流(Parallel Stream)

并行流利用多核 CPU 加速计算,适用于大数据量处理:

List<String> result = list.parallelStream()
.map(String::toUpperCase)
.collect(Collectors.toList());

⚠️ 注意:并行流不保证顺序,且对线程安全要求较高。


六、完整示例代码

import java.util.*;
import java.util.stream.Collectors;class User {
private String name;
private int age;
private String gender;public User(String name, int age, String gender) {
this.name = name;
this.age = age;
this.gender = gender;
}public String getName() { return name; }
public int getAge() { return age; }
public String getGender() { return gender; }@Override
public String toString() {
return name;
}
}public class StreamDemo {
public static void main(String[] args) {
List<User> users = Arrays.asList(
new User("Alice", 25, "Female"),
new User("Bob", 30, "Male"),
new User("Charlie", 22, "Male"),
new User("Diana", 28, "Female")
);// 案例1:过滤 + 映射 + 收集
List<String> maleNames = users.stream()
.filter(u -> "Male".equals(u.getGender()))
.map(User::getName)
.collect(Collectors.toList());
System.out.println("Male names: " + maleNames);// 案例2:分组 + 统计
Map<String, Double> avgAgeByGender = users.stream()
.collect(Collectors.groupingBy(User::getGender,
Collectors.averagingInt(User::getAge)));
System.out.println("Average age by gender: " + avgAgeByGender);// 案例3:并行流求和
int totalAge = users.parallelStream()
.mapToInt(User::getAge)
.sum();
System.out.println("Total age: " + totalAge);// 案例4:查找最年长用户
Optional<User> oldest = users.stream()
.max(Comparator.comparing(User::getAge));
System.out.println("Oldest user: " + oldest.orElse(null));
}
}

七、Stream 的优势

优势说明
声明式语法用链式调用表达逻辑,代码更简洁
函数式编程支持使用 Lambda 表达式简化操作
链式操作支持中间操作的灵活组合
并行处理利用多核 CPU 提升性能
内置丰富的操作提供过滤、映射、分组、统计等工具

八、注意事项

  1. 流只能消费一次:终端操作后,流关闭,再次使用会抛异常。
  2. 避免副作用:中间操作(如 forEach)不应修改外部状态。
  3. 性能权衡:小数据集使用普通循环更高效,大数据集使用并行流。
  4. 线程安全:并行流操作需确保数据和操作是线程安全的。

九、总结

Java Stream 是一种 声明式 的数据处理工具,通过链式操作简化集合处理,提升了代码的可读性和可维护性。结合 CollectorsOptionalComparator 等工具,可以轻松实现过滤、映射、分组、统计等复杂操作。合理使用 Stream 能显著提高开发效率和代码质量。

http://www.dtcms.com/a/553311.html

相关文章:

  • 如何进入公司网站的后台怎样用vs做简单网站
  • 长春手机建站模板wordpress搜索页
  • 消除链上气泡图:为什么换仓正在成为新的链上生存策略?
  • 什么是TRS收益互换与场外个股期权:从金融逻辑到系统开发实践
  • ARM《8》_制作linux最小根文件系统
  • IntelliJ IDEA 如何全局配置 Maven?避免每次打开新项目重新配置 (适用于 2024~2025 版本)
  • vmware17安装ubuntu2204版本qemu运行armv8处理器uboot运行调试的一些工作
  • 【开题答辩全过程】以 二手房买卖与出租系统的设计与实现为例,包含答辩的问题和答案
  • 河池市城乡住房建设厅网站一人有限公司怎么注册
  • 边缘智能的创新:MLGO微算法科技推出基于QoS感知的边缘大模型自适应拆分推理编排技术
  • 前端面试题总结
  • UE5【插件】一键重命名蓝图变量、事件、函数、宏等(实现批量翻译)
  • UE5【C++】中文注释、编辑器乱码解决方法
  • 鸿蒙Flutter三方库适配指南:08.联合插件开发
  • node做网站怎么知道蜘蛛来过桂林人论坛app
  • 什么语言最适合开发 SaaS 系统:从架构视角的全面分析
  • liosam详解
  • 先知社区文章批量爬虫工具
  • 【STM32】电动车报警系统
  • linux kernel struct clk_init_data结构浅解
  • ▲各类通信算法的FPGA开发学习教程——总目录
  • 2025企业秋招:AI笔试监考如何重塑秋招公平性?
  • Rust开发之常用标准库Trait实践(Display、From/Into)
  • XML与HTML
  • 太原做网站需要多少钱网页设计网站怎么放到域名里
  • 网站开发 费用怎么用PS做网站广告图
  • 算法专题十八:FloodFill算法(使用dfs)
  • 【11408学习记录】考研数学速成:n维随机变量分布函数详解(从定义到边缘分布一网打尽)
  • 网络安全应用题3:网络攻击与防范
  • 做网站设计赚钱吗做攻略的网站好