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

相关推荐
MZ_ZXD00133 分钟前
flask校园学科竞赛管理系统-计算机毕业设计源码12876
java·spring boot·python·spring·django·flask·php
源代码•宸1 小时前
C++高频知识点(十三)
开发语言·c++·经验分享·面经
wa的一声哭了1 小时前
python基础知识pip配置pip.conf文件
java·服务器·开发语言·python·pip·risc-v·os
Kay_Liang2 小时前
MySQL SQL语句精要:DDL、DML与DCL的深度探究
开发语言·数据库·sql·mysql·database
钢铁男儿2 小时前
C# 接口(接口可以继承接口)
java·算法·c#
流形填表2 小时前
AI 助力:如何批量提取 Word 表格字段并导出至 Excel
开发语言·人工智能·word·excel·办公自动化
肉肉不想干后端2 小时前
分布式ID:基于K8s-PodName的百度雪花ID生成方案优化
java
每天吃饭的羊2 小时前
箭头函数(Arrow Functions)和普通函数(Regular Functions)
开发语言·javascript·ecmascript
寻觅~流光2 小时前
封装---统一封装处理页面标题
开发语言·前端·javascript·vue.js·typescript·前端框架·vue