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

Java流式处理-Steam详解

Java 8 引入的 Stream API 是一种强大的处理集合数据的工具,它允许你以声明式方式处理数据集合(如 List、Set 等),并支持多种聚合操作(如过滤、映射、排序、归约等)。Stream API 可以显著提高代码的可读性和简洁性,同时支持并行处理以提升性能。

一、Stream 基础概念

1. 什么是 Stream?
  • Stream 是一种针对集合数据的高级抽象,它不存储数据,而是定义了一系列对数据源(如集合、数组)的操作。
  • Stream 操作是惰性的,只有在终止操作被调用时才会执行。
  • Stream 可以是串行的或并行的,并行流利用多线程提高处理大数据的效率。
2. Stream 的特点
  • 不改变数据源:Stream 操作不会修改原始数据,而是返回一个新的 Stream。
  • 一次性使用:Stream 只能被消费一次,消费后需要重新创建。
  • 延迟执行:中间操作(如 filter、map)只会记录操作,不会立即执行,直到终止操作(如 collect、forEach)被调用。

二、Stream 的创建

1. 从集合创建

java

List<String> list = Arrays.asList("apple", "banana", "cherry");
Stream<String> stream = list.stream(); // 串行流
Stream<String> parallelStream = list.parallelStream(); // 并行流
2. 从数组创建

java

int[] array = {1, 2, 3, 4, 5};
IntStream intStream = Arrays.stream(array);
3. 使用 Stream.of ()

java

Stream<String> stream = Stream.of("apple", "banana", "cherry");
4. 创建无限流

java

// 生成无限序列(0, 2, 4, 6...)
Stream<Integer> evenNumbers = Stream.iterate(0, n -> n + 2);
// 生成随机数流
Stream<Double> randoms = Stream.generate(Math::random);

三、Stream 的中间操作

中间操作返回一个新的 Stream,允许链式调用多个操作。常见的中间操作包括:

1. 过滤元素:filter()

java

List<String> fruits = Arrays.asList("apple", "banana", "cherry", "date");
List<String> filtered = fruits.stream().filter(fruit -> fruit.startsWith("a")) // 保留以 'a' 开头的元素.collect(Collectors.toList()); // [apple]
2. 映射元素:map()

java

List<Integer> numbers = Arrays.asList(1, 2, 3);
List<Integer> squared = numbers.stream().map(n -> n * n) // 平方每个元素.collect(Collectors.toList()); // [1, 4, 9]
3. 扁平化嵌套结构:flatMap()

java

List<List<Integer>> nested = Arrays.asList(Arrays.asList(1, 2),Arrays.asList(3, 4)
);
List<Integer> flattened = nested.stream().flatMap(List::stream) // 将嵌套列表展开为单个流.collect(Collectors.toList()); // [1, 2, 3, 4]
4. 排序:sorted()

java

List<String> names = Arrays.asList("Charlie", "Alice", "Bob");
List<String> sorted = names.stream().sorted() // 自然排序.collect(Collectors.toList()); // [Alice, Bob, Charlie]
5. 去重:distinct()

java

List<Integer> duplicates = Arrays.asList(1, 2, 2, 3, 3, 3);
List<Integer> unique = duplicates.stream().distinct() // 去重.collect(Collectors.toList()); // [1, 2, 3]
6. 截断:limit() 和 skip()

java

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> limited = numbers.stream().limit(3) // 取前3个元素.collect(Collectors.toList()); // [1, 2, 3]List<Integer> skipped = numbers.stream().skip(2) // 跳过前2个元素.collect(Collectors.toList()); // [3, 4, 5]

四、Stream 的终止操作

终止操作触发 Stream 的执行并返回最终结果。常见的终止操作包括:

1. 收集结果:collect()

java

// 收集到 List
List<String> resultList = stream.collect(Collectors.toList());// 收集到 Set
Set<String> resultSet = stream.collect(Collectors.toSet());// 收集到 Map
Map<Integer, String> map = stream.collect(Collectors.toMap(s -> s.length(), // key: 字符串长度s -> s,          // value: 字符串本身(existing, replacement) -> existing // 处理键冲突的策略));
2. 遍历元素:forEach()

java

stream.forEach(System.out::println); // 打印每个元素
3. 聚合操作:reduce()

java

// 求和
int sum = numbers.stream().reduce(0, (a, b) -> a + b); // 初始值为0,累加所有元素// 求最大值
Optional<Integer> max = numbers.stream().reduce(Integer::max); // 返回 Optional 避免空指针
4. 匹配元素:anyMatch()allMatch()noneMatch()

java

boolean anyStartsWithA = stream.anyMatch(s -> s.startsWith("A")); // 是否存在以 'A' 开头的元素
boolean allStartsWithA = stream.allMatch(s -> s.startsWith("A")); // 是否所有元素都以 'A' 开头
boolean noneStartsWithA = stream.noneMatch(s -> s.startsWith("A")); // 是否没有元素以 'A' 开头
5. 查找元素:findFirst()findAny()

java

Optional<String> first = stream.findFirst(); // 返回第一个元素(可能为空)
Optional<String> any = stream.findAny(); // 返回任意元素(并行流中可能随机返回)
6. 统计:count()min()max()

java

long count = stream.count(); // 元素个数
Optional<Integer> min = numbers.stream().min(Integer::compareTo); // 最小值
Optional<Integer> max = numbers.stream().max(Integer::compareTo); // 最大值

五、并行流(Parallel Stream)

并行流利用多核处理器并行执行 Stream 操作,适用于大数据集的高效处理。

1. 创建并行流

java

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Stream<Integer> parallelStream = numbers.parallelStream(); // 直接创建并行流
Stream<Integer> parallelStream2 = numbers.stream().parallel(); // 将串行流转换为并行流
2. 并行流示例

java

long sum = numbers.parallelStream().mapToInt(Integer::intValue).sum(); // 并行求和
3. 注意事项
  • 线程安全:并行流操作涉及多线程,确保操作的数据源和中间操作是线程安全的。
  • 适用场景:对于小数据集或操作本身开销不大的情况,并行流可能比串行流更慢(线程调度开销)。
  • 顺序问题:并行流不保证处理顺序,若需要顺序性,可使用 forEachOrdered() 替代 forEach()

六、Collectors 工具类

Collectors 是一个实用工具类,提供了各种收集器(Collector),用于将 Stream 结果收集到不同的数据结构中。

1. 分组:groupingBy()

java

// 按字符串长度分组
Map<Integer, List<String>> groups = stream.collect(Collectors.groupingBy(String::length));
2. 分区:partitioningBy()

java

// 按条件分区(偶数和奇数)
Map<Boolean, List<Integer>> partitioned = numbers.stream().collect(Collectors.partitioningBy(n -> n % 2 == 0));
3. 连接字符串:joining()

java

String joined = stream.collect(Collectors.joining(", ")); // 用逗号连接元素
4. 统计:summarizingInt()

java

IntSummaryStatistics stats = numbers.stream().collect(Collectors.summarizingInt(Integer::intValue));
// stats 包含 count, sum, min, max, average

七、Stream 与 Lambda 表达式结合

Stream API 与 Lambda 表达式紧密结合,使代码更简洁。例如:

java

// 传统方式
List<String> filtered = new ArrayList<>();
for (String fruit : fruits) {if (fruit.startsWith("a")) {filtered.add(fruit);}
}// Stream + Lambda 方式
List<String> filtered = fruits.stream().filter(fruit -> fruit.startsWith("a")).collect(Collectors.toList());

八、常见使用场景

1. 数据过滤与转换

java

List<Product> products = getProducts();
List<String> productNames = products.stream().filter(p -> p.getPrice() > 100) // 过滤价格大于100的产品.map(Product::getName) // 提取产品名称.collect(Collectors.toList());
2. 聚合统计

java

double averagePrice = products.stream().mapToDouble(Product::getPrice).average() // 计算平均价格.orElse(0.0);
3. 并行处理

java

// 并行计算所有产品的总价格
double totalPrice = products.parallelStream().mapToDouble(Product::getPrice).sum();

总结

Java Stream API 通过声明式方式处理集合数据,使代码更简洁、易读,并支持并行处理以提高性能。关键要点:

  • 中间操作(如 filtermap)返回新的 Stream,支持链式调用。
  • 终止操作(如 collectforEach)触发执行并产生结果。
  • 并行流适用于大数据集的高效处理,但需注意线程安全和适用场景。
  • Collectors 工具类提供丰富的收集器,用于结果转换和聚合。

相关文章:

  • 【Fifty Project - D30】
  • 告别手抖困扰:全方位健康护理指南
  • 《AI 绘画崛起,人类艺术家如何在夹缝中寻找新机遇?》
  • 电磁兼容(EMC)仿真(精编版)
  • MYSQL之复合查询
  • 实验13 数据库权限管理
  • Python语法特点与编码规范
  • CDGA|一线二线企业数据治理项目目前发展状况
  • 江科大DMA直接存储器访问hal库实现
  • Pytorch里面多任务Loss是加起来还是分别backward? | Pytorch | 深度学习
  • @JsonFormat时区问题
  • AB Sciex QTRAP 4500联用 Waters I Class plus 到货后如何安装和性能测试
  • Flink集成资源管理器
  • Android.mk解析
  • Web前端开发: 什么是JavaScript?
  • HC32f460的定时器时间分析
  • 可视化图解算法44:旋转数组的最小数字
  • 图解深度学习 - 特征工程(DL和ML的核心差异)
  • 决策树引导:如何选择最适合你的机器学习算法
  • [20250522]目前市场上主流AI开发板及算法盒子的芯片配置、架构及支持的AI推理框架的详细梳理
  • 有什么平台做网站比较好/全网营销软件
  • 合肥包河区最新消息/宁波seo网页怎么优化
  • 政府机关网站备案/口碑营销的产品
  • 做旅行社网站/百度如何推广产品
  • 在那里做网站/客户管理系统
  • 设计师一般放作品的网站/大数据培训机构排名前十