中间操作与终止操作
核心概念对比
| 特性 | 中间操作 (Intermediate Operations) | 终止操作 (Terminal Operations) |
|---|---|---|
| 返回值 | Stream<T> | 非 Stream 类型(void、具体类型、Optional 等) |
| 执行时机 | 惰性执行(Lazy) | 立即执行(Eager) |
| 可链接性 | 可链接多个 | 必须是最后一个操作 |
| 是否触发计算 | 否,只构建管道 | 是,触发整个管道计算 |
| 调用次数 | 可多次调用 | 只能调用一次 |
选择策略
| 需求 | 推荐操作 | 说明 |
|---|---|---|
| 过滤数据 | filter(), distinct() | 中间操作 |
| 转换数据 | map(), flatMap() | 中间操作 |
| 排序 | sorted() | 中间操作 |
| 限制数量 | limit(), skip() | 中间操作 |
| 检查条件 | anyMatch(), allMatch() | 终止操作 |
| 查找元素 | findFirst(), findAny() | 终止操作 |
| 聚合计算 | reduce(), min(), max() | 终止操作 |
| 收集结果 | collect() | 终止操作 |
| 遍历消费 | forEach() | 终止操作 |
中间操作 (Intermediate Operations)
过滤操作
java
// filter(Predicate<T>) - 过滤符合条件的元素
Stream<Integer> evenNumbers = stream.filter(n -> n % 2 == 0);
// distinct() - 去重(基于equals和hashCode)
Stream<String> uniqueWords = stream.distinct();
// limit(long maxSize) - 限制元素数量
Stream<Integer> firstFive = stream.limit(5);
// skip(long n) - 跳过前n个元素
Stream<Integer> afterFirstTwo = stream.skip(2);
// takeWhile(Predicate<T>) - Java 9+,条件满足时取元素
Stream<Integer> lessThanFive = stream.takeWhile(n -> n < 5);
// dropWhile(Predicate<T>) - Java 9+,条件满足时丢弃元素
Stream<Integer> afterSmallNumbers = stream.dropWhile(n -> n < 5);映射操作
java
// map(Function<T, R>) - 一对一映射
Stream<String> names = stream.map(User::getName);
// flatMap(Function<T, Stream<R>>) - 一对多映射(展平)
Stream<String> words = lines.stream()
.flatMap(line -> Arrays.stream(line.split(" ")));
// mapToInt(), mapToLong(), mapToDouble() - 映射为基本类型流
IntStream ages = stream.mapToInt(User::getAge);
// mapMulti() - Java 16+,灵活的多重映射
Stream<Integer> expanded = stream.mapMulti((number, consumer) -> {
if (number % 2 == 0) {
consumer.accept(number);
consumer.accept(number * 10);
}
});排序操作
java
// sorted() - 自然排序
Stream<Integer> sortedNumbers = stream.sorted();
// sorted(Comparator<T>) - 自定义排序
Stream<User> sortedUsers = stream
.sorted(Comparator.comparing(User::getAge).reversed());
// unordered() - 放弃顺序约束(可能提升并行性能)
Stream<Integer> unorderedStream = stream.unordered();查看/调试操作
java
// peek(Consumer<T>) - 查看元素但不修改
Stream<Integer> debugStream = stream
.peek(n -> System.out.println("处理前: " + n))
.map(n -> n * 2)
.peek(n -> System.out.println("处理后: " + n));
// onClose(Runnable) - 设置关闭处理程序
Stream<Integer> streamWithCloseHandler = stream
.onClose(() -> System.out.println("流已关闭"));终止操作 (Terminal Operations)
匹配操作(返回boolean)
java
// anyMatch(Predicate<T>) - 任意元素匹配
boolean hasAdult = users.stream().anyMatch(u -> u.getAge() >= 18);
// allMatch(Predicate<T>) - 所有元素匹配
boolean allValid = data.stream().allMatch(Data::isValid);
// noneMatch(Predicate<T>) - 没有元素匹配
boolean noNegative = numbers.stream().noneMatch(n -> n < 0);查找操作(返回Optional)
java
// findFirst() - 查找第一个元素
Optional<User> firstUser = users.stream().findFirst();
// findAny() - 查找任意元素(并行流中更高效)
Optional<User> anyUser = users.parallelStream().findAny();规约操作(归约、聚合)
java
// reduce(identity, accumulator) - 带初始值的规约
int sum = numbers.stream().reduce(0, Integer::sum);
// reduce(accumulator) - 无初始值的规约
Optional<Integer> max = numbers.stream().reduce(Integer::max);
// reduce(identity, accumulator, combiner) - 支持并行的规约
Integer product = numbers.parallelStream()
.reduce(1, (a, b) -> a * b, (a, b) -> a * b);
// min(Comparator) / max(Comparator) - 最小/最大值
Optional<User> youngest = users.stream()
.min(Comparator.comparingInt(User::getAge));
// count() - 元素计数
long userCount = users.stream().count();收集操作(转换为集合或其他结构)
java
// collect(Collector) - 使用预定义收集器
List<String> names = users.stream()
.map(User::getName)
.collect(Collectors.toList());
Set<String> uniqueNames = users.stream()
.map(User::getName)
.collect(Collectors.toSet());
Map<Long, User> idToUser = users.stream()
.collect(Collectors.toMap(User::getId, Function.identity()));
// 分组
Map<String, List<User>> usersByCity = users.stream()
.collect(Collectors.groupingBy(User::getCity));
// 分区
Map<Boolean, List<User>> partitioned = users.stream()
.collect(Collectors.partitioningBy(u -> u.getAge() >= 18));
// 连接字符串
String joined = users.stream()
.map(User::getName)
.collect(Collectors.joining(", ", "[", "]"));
// 统计
IntSummaryStatistics stats = users.stream()
.collect(Collectors.summarizingInt(User::getAge));遍历/消费操作
java
// forEach(Consumer<T>) - 遍历所有元素
users.stream().forEach(System.out::println);
// forEachOrdered(Consumer<T>) - 保持顺序的遍历
users.parallelStream().forEachOrdered(System.out::println);
// iterator() - 获取迭代器
Iterator<User> iterator = users.stream().iterator();
// spliterator() - 获取分割迭代器(用于并行)
Spliterator<User> spliterator = users.stream().spliterator();数组转换
java
// toArray() - 转换为Object数组
Object[] array = stream.toArray();
// toArray(IntFunction<A[]>) - 转换为指定类型数组
String[] stringArray = stream.toArray(String[]::new);
// toArray() for primitive streams
int[] intArray = intStream.toArray();基本类型流的特有操作
java
// IntStream/LongStream/DoubleStream 特有
int sum = intStream.sum();
OptionalDouble average = doubleStream.average();
OptionalInt min = intStream.min();
OptionalInt max = intStream.max();
IntSummaryStatistics stats = intStream.summaryStatistics();
朔风