1. 引言

Stream API 是 Java 8 引入的核心特性之一。简单来说,这个 API 让我们能够通过声明式编程的方式,更便捷高效地处理集合和其他元素序列。

2. 原始类型流

Stream API 主要针对对象集合设计,而非原始类型。幸运的是,为了支持最常用的三种原始类型——intlongdouble——标准库提供了三个专用实现:IntStreamLongStreamDoubleStream

原始类型流之所以受限,主要因为:

  • ⚠️ 避免装箱/拆箱带来的性能开销
  • 为其他原始类型创建专用流在多数场景下收益有限

3. 算术运算

原始类型流提供了一系列便捷的算术操作方法,如 minmaxsumaverage

int[] integers = new int[] {20, 98, 12, 7, 35};
int min = Arrays.stream(integers)
  .min()
  .getAsInt(); // 返回 7

代码解析:

  1. 通过 Arrays.stream(int[]) 创建 IntStream
  2. 调用 min() 获取最小值(返回 OptionalInt
  3. 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():结束值包含

范围操作仅适用于 IntStreamLongStream

可替代传统 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 仓库 获取。


原始标题:Primitive Type Streams in Java 8

» 下一篇: JUnit 5 @Test 注解