
Java Stream 是 Java 8 引入的数据处理 API允许以函数式编程风格对集合、数组等数据源进行声明式操作。相比传统循环Stream 代码更简洁、可读性更强且天然支持并行处理。核心特性不存储数据Stream 不是数据结构它只是从数据源集合、数组、I/O 通道传递元素进行处理。惰性求值中间操作如filter、map不会立即执行只有终端操作如collect、forEach触发时才真正计算。一次性使用Stream 只能遍历一次消费后即关闭需重新从数据源获取新流。支持并行通过parallelStream()启用多核并行但需注意线程安全与性能开销。常用操作方法详解1. filter数据过滤ListString result Arrays.asList(wp, wwp, wwpp, wwpptt, wwppdd).stream() .filter(str - str.length() 3) .filter(str - str.contains(pp)) .collect(Collectors.toList()); // 结果: [wwpp, wwpptt, wwppdd]2. Predicate 组合and / or / negate利用Predicate接口实现复杂条件的复用与组合。PredicateString lenGe3 str - str.length() 3; PredicateString hasPp str - str.contains(pp); PredicateString hasDd str - str.contains(dd); // 逻辑: (长度3 AND 包含pp) OR 包含dd ListString result Arrays.asList(wp, wwp, wwpp, wwpptt, wwppdd).stream() .filter(lenGe3.and(hasPp).or(hasDd)) .collect(Collectors.toList()); // 结果: [wwpp, wwpptt, wwppdd]3. forEach遍历消费注意forEach是终端操作不应在内部修改外部状态非线程安全。如需收集结果请用collect。javaArrays.asList(wp, wwp, wwpp, wwpptt, wwppdd).stream() .filter(str - str.length() 3) .forEach(item - System.out.println(hello: item)); // 输出: hello: wwp / hello: wwpp / hello: wwpptt / hello: wwppdd4. sorted排序表格场景方法自然升序sorted()自然降序sorted(Comparator.reverseOrder())Null 安全排序sorted(Comparator.nullsFirst/naturalOrder())按属性排序sorted(Comparator.comparing(Entity::getField))多字段排序comparing(...).thenComparing(...)// 将空元素认为小于非空元素后升序nullsFirst naturalOrder 的结果是 null 在最前其余升序 Arrays.asList(wp, wwp, pp, wwpptt, wwppdd, w, null).stream() .sorted(Comparator.nullsFirst(Comparator.naturalOrder())) .forEach(System.out::println); // 结果: null, pp, w, wp, wwp, wwppdd, wwpptt // 按字符串长度升序 Arrays.asList(wp, wwp, pp, wwpptt, wwppdd, w).stream() .sorted(Comparator.comparing(String::length)) .forEach(System.out::println); // 结果: w, wp, pp, wwp, wwpptt, wwppdd5. distinct去重基于元素的equals()和hashCode()方法。对于自定义对象务必正确重写这两个方法。ListString result Arrays.asList(wp, wp, pp, pp, tt, w).stream() .distinct() .collect(Collectors.toList()); // 结果: [wp, pp, tt, w]6. limit skip截取与跳过// limit: 取前 N 个 Arrays.asList(wpe, wp, ppff, p, tt, w).stream() .sorted(Comparator.comparing(String::length)) .limit(3) .collect(Collectors.toList()); // 结果: [p, w, wp] (长度分别为1,1,2) // skip: 跳过前 N 个 (常与 limit 配合实现分页) list.stream().skip(10).limit(10).collect(Collectors.toList());7. max min极值返回OptionalT避免空集合导致的异常。javaOptionalString max Stream.of(wpp, wp, pp, tt, w) .max(Comparator.comparing(String::length)); // max.get() wpp8. map vs flatMap重点操作作用映射关系map一对一转换T → RflatMap一对多转换扁平化T → StreamR// map: 提取属性 ListString names students.stream() .map(Student::getName) .collect(Collectors.toList()); // flatMap: 嵌套集合扁平化 过滤null ListListInteger nested List.of( List.of(1, 44, null, 4), List.of(55), List.of(99, -2) ); ListInteger flat nested.stream() .flatMap(Collection::stream) // 展平 .filter(Objects::nonNull) // 过滤null .collect(Collectors.toList()); // 结果: [1, 44, 4, 55, 99, -2]9. reduce归约聚合补充将流中元素反复结合起来得到一个值是sum/count/max/min的通用形式。// 求和 int sum Stream.of(1, 2, 3, 4).reduce(0, Integer::sum); // 拼接字符串 String joined Stream.of(a, b, c) .reduce(, (a, b) - a , b);10. Collectors.teeing双路收集Java 12一次遍历同时执行两个收集器再合并结果。注意返回值类型匹配。//计算集合数据中的元素数量和元素之合 MapString, Object stats Stream.of(2, 11, 1, 5, 7, 8, 12) .collect(Collectors.teeing( Collectors.counting(), Collectors.summingInt(e - e), (count, sum) - Map.of(count, count, sum, sum) )); // 结果: {count7, sum46}11. groupingBy多级分组// 按部门分组 → 再按职位分组 → 计数 MapString, MapString, Long result employees.stream() .collect(Collectors.groupingBy( Employee::getDept, Collectors.groupingBy(Employee::getPosition, Collectors.counting()) ));12. Optional 的 orElse vs orElseGet方法参数执行时机适用场景orElse(T)具体值无论是否为空都执行默认值是常量/已创建的对象orElseGet(Supplier)Lambda仅在为空时执行默认值需要创建/查询/计算// 推荐避免不必要的数据库查询 User user optionalUser.orElseGet(() - userService.getDefaultUser());13. takeWhile dropWhileJava 9针对有序流的条件截取遇到第一个不满足条件的元素即停止。// takeWhile: 取前面连续满足条件的部分 ListInteger result Stream.of(1, 3, 5, 100, 2, 4) .takeWhile(n - n 100) .collect(Collectors.toList()); // 结果: [1, 3, 5] (遇到100停止后面的2,4被丢弃) // dropWhile: 丢弃前面连续满足条件的部分 // 结果: [100, 2, 4]14. peek调试利器补充中间操作用于在不改变流的情况下观察元素常用于日志打印。ListString result list.stream() .filter(s - s.length() 2) .peek(s - log.debug(过滤后: {}, s)) // 调试 .map(String::toUpperCase) .peek(s - log.debug(转换后: {}, s)) // 调试 .collect(Collectors.toList());生产环境避坑指南parallelStream 慎用共享默认ForkJoinPool.commonPool()CPU 密集型任务会阻塞其他并行流。数据量小1万或链表结构时并行反而更慢拆分合并开销 收益。涉及共享可变状态如ArrayList.add会导致数据错乱。避免在 Stream 中修改外部变量// 危险并行下非线程安全 ListString bad new ArrayList(); stream.forEach(bad::add); // 正确使用 collect ListString good stream.collect(Collectors.toList());NullPointerException 防护map可能产生 null 元素后续操作需防御。max/min/get()在空流时抛异常优先用orElse/orElseGet。排序时若含 null 必须使用Comparator.nullsFirst/nullsLast。流的复用问题StreamString s list.stream(); s.filter(...).collect(...); s.map(...).collect(...); // IllegalStateException: stream has already been operated upon性能建议先filter再map减少转换次数。大数据集考虑limit提前截断。简单循环能解决的问题不要强行用 Stream过度设计。选型参考需求推荐 API过滤filter转换map/flatMap排序sorted去重distinct截取limit/skip/takeWhile聚合reduce/collect统计count/summarizingInt/teeing分组groupingBy/partitioningBy查找findFirst/findAny/anyMatch调试peek