1. 引言
Stream API 是 Java 8 引入的核心特性之一。简单来说,这个 API 让我们能够通过声明式编程的方式,更便捷高效地处理集合和其他元素序列。
2. 原始类型流
Stream API 主要针对对象集合设计,而非原始类型。幸运的是,为了支持最常用的三种原始类型——int、long 和 double——标准库提供了三个专用实现:IntStream、LongStream 和 DoubleStream。
原始类型流之所以受限,主要因为:
- ⚠️ 避免装箱/拆箱带来的性能开销
- 为其他原始类型创建专用流在多数场景下收益有限
3. 算术运算
原始类型流提供了一系列便捷的算术操作方法,如 min、max、sum 和 average:
int[] integers = new int[] {20, 98, 12, 7, 35};
int min = Arrays.stream(integers)
.min()
.getAsInt(); // 返回 7
代码解析:
- 通过
Arrays.stream(int[])
创建 IntStream - 调用
min()
获取最小值(返回OptionalInt
) - 用
getAsInt()
提取原始值
另一种创建方式是 IntStream.of(int...)
,max()
方法同理:
int max = IntStream.of(20, 98, 12, 7, 35)
.max()
.getAsInt(); // 返回 98
求和操作更简单,sum()
直接返回原始值:
int sum = IntStream.of(20, 98, 12, 7, 35).sum(); // 返回 172
计算平均值时注意返回类型:
double avg = IntStream.of(20, 98, 12, 7, 35)
.average()
.getAsDouble(); // 返回 34.4
4. 范围操作
可以通过范围创建 IntStream:
int sum = IntStream.range(1, 10)
.sum(); // 返回 45 (1+2+...+9)
int sum = IntStream.rangeClosed(1, 10)
.sum(); // 返回 55 (1+2+...+10)
关键区别:
- ✅
range()
:结束值不包含 - ✅
rangeClosed()
:结束值包含
范围操作仅适用于 IntStream 和 LongStream
可替代传统 for 循环:
IntStream.rangeClosed(1, 5)
.forEach(System.out::println);
还能轻松实现并行处理:
IntStream.rangeClosed(1, 5)
.parallel()
.forEach(System.out::println);
⚠️ 踩坑提示:虽然这种函数式写法很炫,但简单迭代场景下,传统 for 循环在可读性和性能上往往更优。
5. 装箱与拆箱
需要将原始类型转为包装类时,使用 boxed()
:
List<Integer> evenInts = IntStream.rangeClosed(1, 10)
.filter(i -> i % 2 == 0)
.boxed()
.collect(Collectors.toList());
反向转换使用 mapToXxx
方法:
// 返回 78
int sum = Arrays.asList(33,45)
.stream()
.mapToInt(i -> i)
.sum();
核心转换方法:
- ✅
mapToInt()
/mapToLong()
/mapToDouble()
- ✅
flatMapToXxx()
系列方法
6. 总结
Java Stream API 是语言层面的重大增强。本文仅探讨了原始类型流的冰山一角,但已足够应对实际开发需求。
所有示例代码可在 GitHub 仓库 获取。