Java Stream 流详解 Java 8 引入了 Stream
API,它是一种 声明式 处理数据的方式,旨在简化集合类的操作。Stream
允许你以声明性方式处理集合、数组、I/O 通道等的数据流,支持并行处理,并能简洁地执行过滤、映射、排序等操作。
✅ 1. 什么是 Stream Stream
是一种 数据流 ,不是数据存储结构。它允许你以一种 函数式 的方式处理集合中的数据,通过流水线方式进行操作,支持 惰性计算 (即只有在最终操作时才会执行)。Stream
操作通常分为两大类:
中间操作 (Intermediate Operations):返回一个新的流,支持链式调用,操作是惰性求值的。
终止操作 (Terminal Operations):触发流的计算,并产生一个结果(如聚合、输出等),一旦执行终止操作,流就不可再被使用。
✅ 2. Stream 的常见创建方式 Stream 可以通过以下几种方式创建:
2.1 从集合中创建 Stream 1 2 3 4 5 6 7 8 9 10 11 12 13 import java.util.Arrays;import java.util.List;import java.util.stream.Stream;public class StreamExample { public static void main (String[] args) { List<String> list = Arrays.asList("apple" , "banana" , "cherry" ); Stream<String> stream = list.stream(); stream.forEach(System.out::println); } }
2.2 从数组中创建 Stream 1 2 3 String[] arr = {"apple" , "banana" , "cherry" }; Stream<String> stream = Arrays.stream(arr); stream.forEach(System.out::println);
2.3 创建无限流 使用 Stream
的 generate
或 iterate
方法可以创建无限流。
1 2 3 4 5 6 7 Stream<Double> randomNumbers = Stream.generate(Math::random); randomNumbers.limit(5 ).forEach(System.out::println); Stream<Integer> numbers = Stream.iterate(0 , n -> n + 2 ); numbers.limit(5 ).forEach(System.out::println);
✅ 3. Stream 中的常见中间操作 中间操作是惰性计算的,即它们只会在终止操作触发时被执行。常见的中间操作包括:
3.1 filter()
根据条件过滤流中的元素。
1 2 3 4 List<String> list = Arrays.asList("apple" , "banana" , "cherry" , "date" ); list.stream() .filter(s -> s.startsWith("a" )) .forEach(System.out::println);
3.2 map()
对流中的每个元素应用转换函数。
1 2 3 4 List<String> list = Arrays.asList("apple" , "banana" , "cherry" ); list.stream() .map(String::toUpperCase) .forEach(System.out::println);
3.3 distinct()
去重,返回一个没有重复元素的新流。
1 2 3 4 List<Integer> list = Arrays.asList(1 , 2 , 3 , 3 , 4 , 5 , 5 ); list.stream() .distinct() .forEach(System.out::println);
3.4 sorted()
排序,默认按自然顺序排序,或者传入自定义的比较器。
1 2 3 4 List<Integer> list = Arrays.asList(3 , 1 , 4 , 1 , 5 ); list.stream() .sorted() .forEach(System.out::println);
3.5 limit()
限制流的元素数量。
1 2 3 4 List<Integer> list = Arrays.asList(1 , 2 , 3 , 4 , 5 ); list.stream() .limit(3 ) .forEach(System.out::println);
3.6 skip()
跳过流中的前 N 个元素。
1 2 3 4 List<Integer> list = Arrays.asList(1 , 2 , 3 , 4 , 5 ); list.stream() .skip(2 ) .forEach(System.out::println);
3.7 flatMap()
扁平化流,将一个流中的元素映射为多个元素,并将这些元素扁平化成一个流。
1 2 3 4 5 List<List<String>> list = Arrays.asList( Arrays.asList("a" , "b" ), Arrays.asList("c" , "d" )); list.stream() .flatMap(List::stream) .forEach(System.out::println);
✅ 4. Stream 中的常见终止操作 终止操作会触发整个流的计算,且终止操作执行后,流将无法再使用。
4.1 forEach()
对流中的每个元素执行指定的操作。
1 2 3 List<String> list = Arrays.asList("apple" , "banana" , "cherry" ); list.stream() .forEach(System.out::println);
4.2 collect()
将流中的元素收集到集合中。常用的收集器有 Collectors.toList()
、Collectors.toSet()
、Collectors.joining()
等。
1 2 3 4 5 List<String> list = Arrays.asList("apple" , "banana" , "cherry" ); List<String> result = list.stream() .filter(s -> s.startsWith("a" )) .collect(Collectors.toList()); System.out.println(result);
4.3 reduce()
将流中的元素反复结合起来,得到一个值。通常用于计算总和、乘积等。
1 2 3 4 List<Integer> list = Arrays.asList(1 , 2 , 3 , 4 );int sum = list.stream() .reduce(0 , Integer::sum); System.out.println(sum);
4.4 anyMatch()
判断流中是否有任何一个元素满足给定条件。
1 2 3 4 List<String> list = Arrays.asList("apple" , "banana" , "cherry" );boolean result = list.stream() .anyMatch(s -> s.startsWith("b" )); System.out.println(result);
4.5 allMatch()
判断流中是否所有元素都满足给定条件。
1 2 3 4 List<String> list = Arrays.asList("apple" , "banana" , "cherry" );boolean result = list.stream() .allMatch(s -> s.length() > 4 ); System.out.println(result);
4.6 noneMatch()
判断流中是否没有任何元素满足给定条件。
1 2 3 4 List<String> list = Arrays.asList("apple" , "banana" , "cherry" );boolean result = list.stream() .noneMatch(s -> s.startsWith("z" )); System.out.println(result);
✅ 5. 并行流 Stream
还支持并行处理数据,通过 parallelStream()
或 parallel()
方法,可以实现多核处理,提升性能(尤其是在处理大量数据时)。
1 2 3 4 List<Integer> list = Arrays.asList(1 , 2 , 3 , 4 , 5 ); list.stream() .parallel() .forEach(System.out::println);
注意:并行流并不总是适合所有情况,对于小数据集,可能反而会导致性能下降。
✅ 6. 总结
中间操作 :如 filter()
、map()
、sorted()
等,是惰性求值的,返回一个新的流。
终止操作 :如 forEach()
、collect()
、reduce()
等,触发流的计算并产生结果。
并行流 :Stream
支持并行处理,适合大数据量的处理。
流的特点 :流是一次性的,一旦消费后就无法重用。
通过 Stream API,我们可以更加简洁地处理集合数据,同时支持函数式编程风格。