版本:基于 Java 17 & Java 21 LTS

Stream API 是 Java 8 引入的最具革命性的特性之一。它让你可以以声明式的方式处理数据集合,就像编写 SQL 查询一样简单。本篇将通过实战案例带你精通 Stream 的核心用法。


1. Stream 的生命周期

一个 Stream 操作通常分为三个阶段:

  1. 数据源 (Source):如 List, Set, 数组

  2. 中间操作 (Intermediate Operations):返回一个新的 Stream,可以链式调用。

  3. 终端操作 (Terminal Operations):触发计算并返回结果,一旦执行,Stream 就会关闭。


2. 核心中间操作 (Filter & Map)

Filter (过滤)

根据条件筛选元素。

var names = List.of("Alice", "Bob", "Charlie", "David");
var result = names.stream()
                  .filter(name -> name.startsWith("A"))
                  .toList(); // Alice

Map (映射/转换)

将元素转换成另一种形式。

var lengths = names.stream()
                   .map(String::length) // 转换成名字的长度
                   .toList(); // [5, 3, 7, 5]

3. 核心终端操作 (Collect & ForEach)

Collect (收集)

将 Stream 转换回集合或其他形式。

import java.util.stream.Collectors;

var userMap = names.stream()
                   .collect(Collectors.toMap(
                       name -> name,        // Key
                       name -> name.length() // Value
                   ));

Reduce (规约)

将所有元素合并成一个值(如求和、求最大值)。

var sum = List.of(1, 2, 3, 4).stream()
                             .reduce(0, Integer::sum); // 10

4. 排序与去重 (Sorted & Distinct)

var numbers = List.of(3, 1, 4, 1, 5, 9);
var sortedUnique = numbers.stream()
                          .distinct() // 去重
                          .sorted()   // 排序
                          .toList();  // [1, 3, 4, 5, 9]

5. 并行流 (Parallel Streams)

如果你处理的是海量数据,可以使用并行流来利用多核 CPU 的性能。

var hugeList = java.util.stream.LongStream.rangeClosed(1, 1_000_000).boxed().toList();

// 串行
long start = System.currentTimeMillis();
hugeList.stream().map(Math::sqrt).count();
System.out.println("串行耗时: " + (System.currentTimeMillis() - start));

// 并行
start = System.currentTimeMillis();
hugeList.parallelStream().map(Math::sqrt).count();
System.out.println("并行耗时: " + (System.currentTimeMillis() - start));

注意:并行流并不总是更快。对于简单操作或小数据量,线程管理的开销反而会让它变慢。


6. Java 16+ 新特性:.toList()

在 Java 16 之前,你需要写长长的 .collect(Collectors.toList())。现在可以直接写 .toList(),它返回的是一个不可变的列表。

// 现代写法
var modernList = Stream.of("a", "b").toList(); 

本章小结

第九篇我们实战了:

  1. Stream 的三个阶段:源、中间操作、终端操作。

  2. 如何使用 filter 筛选数据,map 转换数据。

  3. 使用 Collectors 进行复杂的结果收集。

  4. 利用 parallelStream 处理大数据。

  5. Java 16+ 带来的简洁 .toList() 语法。

下一篇预告:多线程与并发基础 (Thread, Runnable, ExecutorService, Virtual Threads)