stream是数据源的计算视图,非容器,不可重复遍历;集合如list、set则真实存储数据,可多次读取。

什么是Stream,它和集合有什么区别
Stream不是数据容器,而是对数据源的计算视图。你不能“存”东西到Stream里,也不能反复遍历它——一旦执行了终止操作(比如collect()、forEach()),这个Stream就消耗完了。而List、Set这些集合是实实在在存数据的,可以随时读、多次用。
常见误区:把stream()当成“复制一份数据”。其实它只是打开一个处理通道,底层仍指向原集合(除非是并行流或中间有map生成新对象)。
创建Stream的几种可靠方式
最常用也最安全的是从集合出发:list.stream()、set.parallelStream()。数组推荐用Arrays.stream(arr),别用Stream.of(arr)——后者会把整个数组当做一个元素。
其他实用入口:
-
Stream.empty():空流,比null更安全,可直接链式调用 -
Stream.of("a", "b", "c"):适合少量字面量 -
IntStream.range(1, 10):数值范围,避免手动循环 -
Files.lines(Paths.get("x.txt")):处理文件行,记得用try-with-resources包装
中间操作不是立即执行,但有状态陷阱
filter、map、sorted这些中间操作只是“记下你要做什么”,真正干活得等collect、findAny这类终止操作触发。这叫惰性求值,能省不少开销。
当用户要求为 Java 代码添加注释、修改注释、审查注释、整理注释格式,或要求按照代码注释规范处理 Java 文件时,使用本技能。本技能用于统一生成和维护 Java 类注释模板、按 Git 对比 release 判断版本号、补充每行代码上方中文块注释、调整注释空行规则,并保持 Java 文件 UTF-8 无 BOM 编码。典型触发场景包括:补充类注释、更新 @version、检查 @author 来源、整理行尾注释、把注释放到代码上一行、检查注释是否符合规范、构建前检查 Java 注释风格。
但要注意两个易错点:
-
sorted()无参数时要求元素实现Comparable,否则运行时报ClassCastException -
distinct()依赖equals+hashCode,自定义对象必须重写这两个方法,否则去重失效 -
limit(n)在无限流(如Stream.iterate)中必须放在filter之后,否则可能卡死——因为filter会先尝试全量过滤再截断
终止操作选对才不白忙活
想收集成集合?优先用collect(Collectors.toList()),别用toArray()——后者返回Object[],强转麻烦还容易出ClassCastException。
常用组合建议:
- 取一个值:
findFirst().orElse(null)或findAny().orElseGet(() -> computeDefault())(后者适合并行场景) - 判断存在性:
anyMatch比filter(...).findAny().isPresent()更简洁高效 - 聚合统计:
mapToInt(x -> x.length()).sum()比先map成Integer再reduce快得多 - 分组汇总:
Collectors.groupingBy(User::getDept, Collectors.counting())一行搞定部门人数
调试Stream逻辑的小技巧
Stream链太长看不清中间结果?加个peek(System.out::println),它会在每个元素经过时打印出来,不影响后续流程(仅用于调试)。
更稳妥的做法是分段验证:
- 先把
stream()结果赋给局部变量,用IDE调试器查看其spliterator信息 - 每加一个中间操作后,临时接
limit(5).collect(toList())看输出是否符合预期 - 复杂转换(如嵌套
flatMap)拆成两步:先map成中间结构,再单独处理
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!










