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,也算是给我这个老鸟上了一课。

相关推荐
m0_748233649 分钟前
C++与Python:内存管理与指针的对比
java·c++·python
软件20527 分钟前
【JDK、JRE、JVM】
java·开发语言·jvm
Wind哥29 分钟前
VS Code搭建C/C++开发调试环境-Windows
c语言·开发语言·c++·visual studio code
m0_7482554137 分钟前
TailwindCSS vs UnoCSS 性能深度对决:究竟快多少?
java
薛家明39 分钟前
easy-query暴打efcore(包括其他所有orm),隐式Group看我如何在子查询做到极致的性能天花板
java·orm·efcore·easy-query·entityframeworkcore·dotnetcore
csbysj202042 分钟前
CSS 属性选择器详解
开发语言
彭同学她同桌1 小时前
Mac-终端
开发语言·javascript·macos
YUFENGSHI.LJ1 小时前
Flutter 高性能 Tab 导航:懒加载与状态保持的最佳实践
开发语言·flutter·1024程序员节
wudl55661 小时前
JDK 21 API增强详解
java·开发语言·windows
β添砖java1 小时前
JS基础Day01
开发语言·javascript·ecmascript