Java Stream API #

一、Stream概述 #

1.1 什么是Stream #

Stream是Java 8引入的用于处理集合的API,支持函数式编程风格。

1.2 Stream特点 #

  • 声明式编程
  • 链式操作
  • 惰性求值
  • 可并行处理

1.3 Stream vs Collection #

特性 Stream Collection
存储 不存储数据 存储数据
操作 惰性求值 立即执行
消费 只能消费一次 可多次遍历

二、创建Stream #

2.1 从集合创建 #

java
List<String> list = Arrays.asList("A", "B", "C");

Stream<String> stream1 = list.stream();
Stream<String> stream2 = list.parallelStream();  // 并行流

2.2 从数组创建 #

java
String[] array = {"A", "B", "C"};

Stream<String> stream1 = Arrays.stream(array);
Stream<String> stream2 = Stream.of("A", "B", "C");

2.3 创建无限流 #

java
// iterate
Stream<Integer> iterate = Stream.iterate(0, n -> n + 2);
iterate.limit(10).forEach(System.out::println);

// generate
Stream<Double> generate = Stream.generate(Math::random);
generate.limit(5).forEach(System.out::println);

2.4 创建空流 #

java
Stream<String> empty = Stream.empty();

三、中间操作 #

3.1 filter过滤 #

java
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

List<Integer> evens = numbers.stream()
    .filter(n -> n % 2 == 0)
    .collect(Collectors.toList());
// [2, 4, 6, 8, 10]

3.2 map映射 #

java
List<String> names = Arrays.asList("alice", "bob", "charlie");

List<String> upperNames = names.stream()
    .map(String::toUpperCase)
    .collect(Collectors.toList());
// [ALICE, BOB, CHARLIE]

// flatMap扁平化
List<List<Integer>> nested = Arrays.asList(
    Arrays.asList(1, 2),
    Arrays.asList(3, 4)
);

List<Integer> flat = nested.stream()
    .flatMap(Collection::stream)
    .collect(Collectors.toList());
// [1, 2, 3, 4]

3.3 sorted排序 #

java
List<Integer> numbers = Arrays.asList(3, 1, 4, 1, 5, 9);

List<Integer> sorted = numbers.stream()
    .sorted()
    .collect(Collectors.toList());
// [1, 1, 3, 4, 5, 9]

List<Integer> descSorted = numbers.stream()
    .sorted(Comparator.reverseOrder())
    .collect(Collectors.toList());
// [9, 5, 4, 3, 1, 1]

3.4 distinct去重 #

java
List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 3, 3);

List<Integer> distinct = numbers.stream()
    .distinct()
    .collect(Collectors.toList());
// [1, 2, 3]

3.5 limit和skip #

java
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

List<Integer> limited = numbers.stream()
    .limit(5)
    .collect(Collectors.toList());
// [1, 2, 3, 4, 5]

List<Integer> skipped = numbers.stream()
    .skip(5)
    .collect(Collectors.toList());
// [6, 7, 8, 9, 10]

3.6 peek调试 #

java
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

List<Integer> result = numbers.stream()
    .peek(n -> System.out.println("处理: " + n))
    .map(n -> n * 2)
    .peek(n -> System.out.println("结果: " + n))
    .collect(Collectors.toList());

四、终端操作 #

4.1 collect收集 #

java
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");

// 收集为List
List<String> list = names.stream().collect(Collectors.toList());

// 收集为Set
Set<String> set = names.stream().collect(Collectors.toSet());

// 收集为Map
Map<String, Integer> map = names.stream()
    .collect(Collectors.toMap(name -> name, String::length));

// 分组
Map<Integer, List<String>> grouped = names.stream()
    .collect(Collectors.groupingBy(String::length));

// 分区
Map<Boolean, List<String>> partitioned = names.stream()
    .collect(Collectors.partitioningBy(s -> s.length() > 3));

// 连接字符串
String joined = names.stream()
    .collect(Collectors.joining(", "));
// Alice, Bob, Charlie

4.2 forEach遍历 #

java
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");

names.stream().forEach(System.out::println);
names.forEach(System.out::println);  // 简化写法

4.3 count计数 #

java
long count = names.stream()
    .filter(s -> s.length() > 3)
    .count();

4.4 reduce归约 #

java
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

// 求和
int sum = numbers.stream()
    .reduce(0, Integer::sum);

// 求最大值
Optional<Integer> max = numbers.stream()
    .reduce(Integer::max);

// 求最小值
Optional<Integer> min = numbers.stream()
    .reduce(Integer::min);

4.5 find查找 #

java
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");

// 查找第一个
Optional<String> first = names.stream().findFirst();

// 查找任意一个(并行流更高效)
Optional<String> any = names.stream().findAny();

4.6 match匹配 #

java
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

// 是否所有元素满足条件
boolean allMatch = numbers.stream().allMatch(n -> n > 0);

// 是否存在元素满足条件
boolean anyMatch = numbers.stream().anyMatch(n -> n > 3);

// 是否所有元素都不满足条件
boolean noneMatch = numbers.stream().noneMatch(n -> n < 0);

4.7 min和max #

java
List<Integer> numbers = Arrays.asList(3, 1, 4, 1, 5, 9);

Optional<Integer> min = numbers.stream().min(Integer::compare);
Optional<Integer> max = numbers.stream().max(Integer::compare);

五、并行流 #

5.1 创建并行流 #

java
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

Stream<Integer> parallel1 = numbers.parallelStream();
Stream<Integer> parallel2 = numbers.stream().parallel();

5.2 并行流操作 #

java
long count = numbers.parallelStream()
    .filter(n -> n % 2 == 0)
    .count();

5.3 注意事项 #

  • 确保操作是无状态的
  • 避免共享可变状态
  • 注意线程安全问题

六、原始类型流 #

6.1 IntStream #

java
// 创建
IntStream range = IntStream.range(1, 10);      // [1, 10)
IntStream rangeClosed = IntStream.rangeClosed(1, 10);  // [1, 10]

// 常用操作
int sum = IntStream.range(1, 101).sum();
OptionalDouble avg = IntStream.range(1, 101).average();
OptionalInt max = IntStream.range(1, 101).max();

// 转换
Stream<Integer> boxed = IntStream.range(1, 10).boxed();

6.2 LongStream和DoubleStream #

java
LongStream longStream = LongStream.range(1, 100);
DoubleStream doubleStream = DoubleStream.of(1.0, 2.0, 3.0);

七、总结 #

操作类型 方法
中间操作 filter, map, sorted, distinct, limit, skip
终端操作 collect, forEach, count, reduce, find, match

Stream要点:

  • 中间操作惰性求值
  • 终端操作触发执行
  • Stream只能消费一次
  • 合理使用并行流
最后更新:2026-03-26