一、概述
Java Stream API 是 Java 8 引入的核心功能,用于以声明式方式高效处理集合数据。Stream 不是数据结构,而是对数据源(如集合、数组)的一系列操作管道,支持链式调用,可实现复杂的数据处理逻辑。
二、Stream 的创建
Stream 的创建是使用 Stream API 的第一步,以下是常见的创建方式:
方法 | 说明 | 示例 |
---|---|---|
集合.stream () | 将集合转换为顺序流 | List<String> list = Arrays.asList("a", "b");<br>Stream<String> stream = list.stream(); |
集合.parallelStream () | 将集合转换为并行流(多线程处理) | Stream<String> parallelStream = list.parallelStream(); |
Arrays.stream (数组) | 将数组转换为流 | int[] arr = {1, 2, 3};<br>IntStream stream = Arrays.stream(arr); |
Stream.of (元素...) | 直接通过元素创建流 | Stream<String> stream = Stream.of("a", "b", "c"); |
Stream.iterate (初始值,迭代函数) | 创建无限流(需配合 limit 截断) | Stream<Integer> stream = Stream.iterate(0, n -> n + 2).limit(5);<br>// 结果:0, 2, 4, 6, 8 |
Stream.generate (生成函数) | 创建无限流(需配合 limit 截断) | Stream<Double> stream = Stream.generate(Math::random).limit(3);<br>// 结果:3个随机数 |
三、中间操作(Intermediate Operations)
中间操作会返回一个新的 Stream,可链式调用,不会立即执行(延迟执行),直到终止操作被调用。
1. 过滤与映射
-
filter(Predicate<T> predicate)
功能:过滤出满足条件的元素
示例:java
运行
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5); List<Integer> evenNumbers = numbers.stream() .filter(n -> n % 2 == 0) // 保留偶数 .collect(Collectors.toList()); // 结果:[2, 4]
-
map(Function<T, R> mapper)
功能:将元素转换为另一种类型
示例:java
运行
List<String> names = Arrays.asList("Alice", "Bob"); List<Integer> nameLengths = names.stream() .map(String::length) // 转换为字符串长度 .collect(Collectors.toList()); // 结果:[5, 3]
-
flatMap(Function<T, Stream<R>> mapper)
功能:将嵌套的集合扁平化(将 Stream<Stream<R>> 转换为 Stream<R>)
示例:java
运行
List<List<Integer>> nestedList = Arrays.asList(Arrays.asList(1, 2), Arrays.asList(3, 4)); List<Integer> flatList = nestedList.stream() .flatMap(List::stream) // 扁平化 .collect(Collectors.toList()); // 结果:[1, 2, 3, 4]
2. 排序与去重
-
sorted() / sorted(Comparator<T> comparator)
功能:自然排序 / 自定义排序
示例:java
运行
List<String> names = Arrays.asList("Charlie", "Alice", "Bob"); List<String> sortedNames = names.stream() .sorted() // 自然排序(按字母顺序) .collect(Collectors.toList()); // 结果:[Alice, Bob, Charlie] // 自定义排序(按长度倒序) List<String> sortedByLength = names.stream() .sorted((s1, s2) -> Integer.compare(s2.length(), s1.length())) .collect(Collectors.toList()); // 结果:[Charlie, Alice, Bob]
-
distinct()
功能:去除重复元素(基于 equals () 方法)
示例:java
运行
List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 3, 3); List<Integer> distinctNumbers = numbers.stream() .distinct() .collect(Collectors.toList()); // 结果:[1, 2, 3]
3. 截断与跳过
-
limit(long maxSize)
功能:截断流,保留前 maxSize 个元素
示例: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]
-
skip(long n)
功能:跳过前 n 个元素
示例:java
运行
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5); List<Integer> skipped = numbers.stream() .skip(3) // 跳过前3个 .collect(Collectors.toList()); // 结果:[4, 5]
四、终止操作(Terminal Operations)
终止操作会触发 Stream 的执行,并返回一个结果,之后 Stream 不可再使用。
1. 结果收集
-
collect(Collector<T, A, R> collector)
功能:将流转换为集合或其他数据结构
示例:java
运行
List<String> names = Arrays.asList("Alice", "Bob", "Charlie"); // 转换为 List List<String> nameList = names.stream().collect(Collectors.toList()); // 转换为 Set(自动去重) Set<String> nameSet = names.stream().collect(Collectors.toSet()); // 转换为 Map(键:长度,值:名称;键冲突时保留第一个) Map<Integer, String> nameMap = names.stream() .collect(Collectors.toMap( String::length, name -> name, (existing, replacement) -> existing )); // 结果:{3=Bob, 5=Alice, 7=Charlie}
-
toArray() / toArray(IntFunction<A[]> generator)
功能:将流转换为数组
示例:java
运行
String[] namesArray = names.stream().toArray(String[]::new); // 结果:["Alice", "Bob", "Charlie"]
2. 聚合操作
-
reduce(T identity, BinaryOperator<T> accumulator)
功能:通过累加器对元素进行累计计算(identity 为初始值)
示例:java
运行
List<Integer> numbers = Arrays.asList(1, 2, 3, 4); int sum = numbers.stream().reduce(0, Integer::sum); // 0 + 1 + 2 + 3 + 4 = 10 int product = numbers.stream().reduce(1, (a, b) -> a * b); // 1 * 1 * 2 * 3 * 4 = 24
-
count()
功能:统计元素个数
示例:java
运行
long count = names.stream().count(); // 结果:3
-
sum() / average() / max() / min()(针对数值流)
功能:数值流的聚合操作
示例:java
运行
IntStream intStream = IntStream.of(1, 2, 3, 4); int sum = intStream.sum(); // 10 OptionalDouble avg = IntStream.of(1, 2, 3).average(); // 2.0 OptionalInt max = IntStream.of(1, 2, 3).max(); // 3
3. 匹配与查找
-
anyMatch(Predicate<T> predicate)
功能:判断是否有至少一个元素满足条件
示例:java
运行
boolean hasA = names.stream().anyMatch(name -> name.startsWith("A")); // true(Alice 满足)
-
allMatch(Predicate<T> predicate)
功能:判断是否所有元素都满足条件
示例:java
运行
boolean allLengthGreater2 = names.stream().allMatch(name -> name.length() > 2); // true
-
noneMatch(Predicate<T> predicate)
功能:判断是否所有元素都不满足条件
示例:java
运行
boolean noneStartsWithZ = names.stream().noneMatch(name -> name.startsWith("Z")); // true
-
findFirst()
功能:返回流中的第一个元素(适合顺序流)
示例:java
运行
Optional<String> first = names.stream().findFirst(); // Optional[Alice]
-
findAny()
功能:返回流中的任意一个元素(适合并行流,效率更高)
示例:java
运行
Optional<String> any = names.parallelStream().findAny(); // 可能返回任意元素
4. 遍历
- forEach(Consumer<T> action)
功能:遍历流中的元素
示例:java
运行
names.stream().forEach(System.out::println); // 依次打印:Alice、Bob、Charlie
五、并行流(Parallel Stream)
并行流利用多线程处理数据,适合大数据量场景,可提高处理效率。使用时需注意线程安全(如避免修改共享变量)。
示例:
java
运行
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
// 并行计算总和
int sum = numbers.parallelStream()
.reduce(0, Integer::sum); // 结果:55
六、综合示例
需求:从用户列表中筛选出年龄 > 18 岁的用户,计算他们姓名长度的平均值。
java
运行
class User {
private String name;
private int age;
// 构造器、getter 省略
}
public class StreamDemo {
public static void main(String[] args) {
List<User> users = Arrays.asList(
new User("Alice", 20),
new User("Bob", 17),
new User("Charlie", 22)
);
double avgNameLength = users.stream()
.filter(user -> user.getAge() > 18) // 筛选成年用户
.mapToInt(user -> user.getName().length()) // 转换为姓名长度
.average() // 计算平均值
.orElse(0.0); // 无数据时返回 0.0
System.out.println(avgNameLength); // 结果:(5 + 7) / 2 = 6.0
}
}
七、总结
- 中间操作:用于数据处理,返回新的 Stream(如
filter
、map
、sorted
)。 - 终止操作:触发执行并返回结果(如
collect
、reduce
、forEach
)。 - 并行流:通过
parallelStream()
启用,适合大数据量的并行处理。
合理使用 Stream API 可使代码更简洁、高效,同时增强可读性和可维护性。