Java中的Java 8新特性:Stream API详解
字数 1118 2025-11-08 20:56:50
Java中的Java 8新特性:Stream API详解
一、描述
Java 8引入的Stream API是处理集合(Collection)数据的强大工具,它允许你以声明式方式(关注"做什么"而非"怎么做")处理数据集合。Stream API支持函数式编程风格,可以简化集合操作代码,提高可读性,并且能够透明地进行并行处理以提升性能。它本质上是一个来自数据源(如集合、数组)的元素队列,并支持聚合操作。
二、核心概念与创建Stream
-
Stream特点:
- 不是数据结构:不存储数据,而是通过计算操作转换数据
- 惰性求值:许多操作(如filter、map)是惰性的,只有遇到终止操作时才会执行
- 不可重复使用:每个Stream只能被消费一次
-
创建Stream的三种主要方式:
// 1. 通过集合创建(最常用) List<String> list = Arrays.asList("a", "b", "c"); Stream<String> stream1 = list.stream(); // 顺序流 Stream<String> parallelStream = list.parallelStream(); // 并行流 // 2. 通过数组创建 String[] array = {"a", "b", "c"}; Stream<String> stream2 = Arrays.stream(array); // 3. 通过Stream的静态方法 Stream<String> stream3 = Stream.of("a", "b", "c"); Stream<Integer> stream4 = Stream.iterate(0, n -> n + 2).limit(5); // 无限流 Stream<Double> stream5 = Stream.generate(Math::random).limit(3); // 生成流
三、Stream操作分类与执行流程
Stream操作分为两大类:
-
中间操作:返回Stream本身,可以链式调用,不会立即执行
- 过滤:filter()、distinct()、limit()、skip()
- 映射:map()、flatMap()
- 排序:sorted()
- 查看:peek()
-
终止操作:返回具体结果或产生副作用,触发实际计算
- 匹配:allMatch()、anyMatch()、noneMatch()
- 查找:findFirst()、findAny()
- 规约:reduce()、collect()
- 遍历:forEach()
四、常用中间操作详解
-
filter(Predicate
predicate) :过滤元素List<String> list = Arrays.asList("apple", "banana", "orange", "grape"); Stream<String> filtered = list.stream() .filter(s -> s.length() > 5); // 过滤长度>5的字符串 -
map(Function<T, R> mapper):元素转换
Stream<String> words = Stream.of("hello", "world"); Stream<Integer> lengths = words.map(String::length); // 转换为字符串长度 -
flatMap(Function<T, Stream
> mapper) :扁平化映射List<List<String>> listOfLists = Arrays.asList( Arrays.asList("a", "b"), Arrays.asList("c", "d") ); Stream<String> flatStream = listOfLists.stream() .flatMap(List::stream); // 将多个流合并为一个 -
sorted():排序
Stream<String> sortedStream = list.stream() .sorted(); // 自然排序 Stream<String> customSorted = list.stream() .sorted(Comparator.reverseOrder()); // 自定义排序
五、常用终止操作详解
-
collect(Collector):将流转换为集合
List<String> resultList = list.stream() .filter(s -> s.startsWith("a")) .collect(Collectors.toList()); // 转换为List Set<String> resultSet = list.stream() .collect(Collectors.toSet()); // 转换为Set Map<String, Integer> resultMap = list.stream() .collect(Collectors.toMap( Function.identity(), // key映射函数 String::length // value映射函数 )); -
reduce:规约操作
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5); Optional<Integer> sum = numbers.stream() .reduce(Integer::sum); // 计算总和 Integer sumWithIdentity = numbers.stream() .reduce(0, Integer::sum); // 提供初始值 -
forEach:遍历
list.stream() .filter(s -> s.length() > 3) .forEach(System.out::println); // 遍历每个元素并打印
六、Collectors工具类的常用方法
Collectors提供了丰富的收集器实现:
// 分组
Map<Integer, List<String>> groupByLength = list.stream()
.collect(Collectors.groupingBy(String::length));
// 分区
Map<Boolean, List<String>> partition = list.stream()
.collect(Collectors.partitioningBy(s -> s.length() > 5));
// 连接字符串
String joined = list.stream()
.collect(Collectors.joining(", ", "[", "]"));
// 统计信息
IntSummaryStatistics stats = list.stream()
.collect(Collectors.summarizingInt(String::length));
七、并行流处理
Stream API支持并行处理,可以自动利用多核处理器:
// 顺序流
long count1 = list.stream()
.filter(s -> s.length() > 3)
.count();
// 并行流(自动分配线程处理)
long count2 = list.parallelStream()
.filter(s -> s.length() > 3)
.count();
八、注意事项
- 流的一次性:Stream只能被消费一次,重复使用会抛出IllegalStateException
- 性能考虑:对于小数据量,顺序流可能比并行流更快(避免线程开销)
- 状态干扰:在并行流中避免使用有状态的操作(如sorted()可能影响性能)
- 空值处理:注意Optional类的使用来处理可能为null的结果
Stream API通过声明式的编程风格,让集合操作更加简洁、易读,并且为并行处理提供了透明支持,是现代Java编程中的重要工具。