Java Stream API中peek()方法使用不当引发的生产问题

早上到刚公司同事就给我发了个生产报错日志,Field 'XXX' doesn't have a default value,一看,这不就是表字段为非空字段,插入数据时该字段为空导致的么。

根据日志我定位到了写入具体的是哪张表以及组装数据的代码,示例代码:

java 复制代码
import java.util.List;

public class StudentDao {
    
    private StudentMapper studentMapper;

    public boolean saveBatch(List<StudentEntity> studentList) {
        studentList.stream().peek(studentEntity -> {
            studentEntity.setName("张三");
        });
        return studentMapper.saveBatch(studentList);
    }
}

我乍一看这代码没问题呀, 字段通过peek()方法赋值了呀,怎么还会报错呢?

文中所有peek()方法均指的是:

java 复制代码
Stream<T> peek(Consumer<? super T> action)

此时,我看到我的idea对peek()方法有个波浪线提示,我猜测有可能就是这个peek()写法有问题,于是我将光标放到peek()方法上,提示'Stream.peek()' 的结果已忽略。

当时没明白什么意思,于是我就写了个main方法,将源代码copy运行了一下,发现居然没赋值成功,字段值任然是null。

我当时一脸懵逼,我就在想难道赋值方法没执行吗?于是我就加了1行控制台输出代码并且加了个断点,重新执行后发现控制台没有输出,也没进断点。

这个peek()方法平时用的不多,也没注意去看,只知道它主要是支持调试,很少用它来对集合元素进行赋值,一般对集合元素遍历赋值都用 forEach()方法,于是百度搜了一下,发现了这个方法的真谛

peek()方法是 Strean 接口中的一个中间操作,它允许你在流的每个元素上执行一个操作,但是这个操作是在最终的终端操作执行前进行的。

然而,如果 peek()是流中唯一的操作,那么它实际上不会执行。

这是因为peek ()本身并不是一个 终端操作,它不会触发流的执行。

在Java 8及以后的版本中,流的执行是情性的,这意味着流操作不会立即执行,而是在遇到终端操作时才会实际执行。

什么是终端操作,在Stream API 中终端操作有很多方法,以下举几个例子,在Stream API中搜terminal operation 就会很清楚的发现哪些方法是终端操作了

java 复制代码
<R, A> R collect(Collector<? super T, A, R> collector);
Optional<T> min(Comparator<? super T> comparator);
Optional<T> max(Comparator<? super T> comparator);
long count();
void forEach(Consumer<? super T> action);

总结一下,就是peek()方法中的代码要执行,必须后面要跟上终端操作方法,不然代码不会执行。

问题定位了,于是乎,我连忙打开代码提交记录,先看下是谁写的代码,把问题的锅先甩出去再说(PS:此处奸笑一下),最后发现这个代码1个将近10年开发经验的老鸟写的,不过这哥们已经离职了。不过这个BUG,也算是给我这个老鸟上了一课。

相关推荐
天下无敌笨笨熊1 分钟前
C#Modbus串口开发心得
开发语言·c#
电商API_180079052471 分钟前
电商商品价格监控工具淘宝京东商品价格抓取API项目实操分享
java·大数据·开发语言·前端·数据挖掘
zzzll11112 分钟前
深度剖析:HashMap 并发死循环与 ConcurrentHashMap 两代演进全解
java·开发语言
如意猴4 分钟前
【C++】001--C++入门(1)
开发语言·c++
秋名RG14 分钟前
2026/5/27 生产事故复盘与整改方案
java
传奇开心果编程28 分钟前
【Rust入门知识点学与练】第10课:Option 和 Result(错误处理入门)
开发语言·学习·rust
leonkay43 分钟前
C# 锁机制——【2】深入原理
开发语言·后端·spring·c#·个人开发
血小板要健康1 小时前
链表 阶段算法总结
java·数据结构·笔记·算法·leetcode·链表
坐吃山猪1 小时前
【多线程】CompletableFuture使用
java·开发语言·多线程
CHPCWWHSU1 小时前
DeepSeek-Harness-Qt将浏览器端Agent装入桌面应用
开发语言·qt