当前位置: 首页 > web >正文

JAVA后端开发——forEach 与方法引用(::)详解

1、案例代码

@Overridepublic  List<ModelDetailVo> selectModelList(ModelQuery query){List<ModelDetailVo> modelList = modelMapper.selectModelList(query);modelList.forEach(this::enrichModelDetailVo);return modelList;}private ModelDetailVo enrichModelDetailVo(ModelDetailVo vo) {if (vo == null) {return null;}if (vo.getSizeInBytes() != null) {vo.setSizeFormatted(formatBytes(vo.getSizeInBytes()));}if (vo.getModelTypeId() != null) {String typeName = DictUtils.getDictLabel("cloud_model_type", String.valueOf(vo.getModelTypeId()));vo.setModelTypeName(typeName);}return vo;}

这段代码的核心功能是:遍历 modelList 集合中的每一个 ModelDetailVo 对象,并对每个对象执行 enrichModelDetailVo 这个方法。这种写法是传统 for 循环的现代化替代方案,它利用了 Java 8 的函数式编程特性,使代码更简洁、更具表达力。

这个结构可以拆解为两个核心组件来理解:

  1. forEach() 方法。

  2. 方法引用 (::) 操作符。

2. 核心知识点一:List.forEach() 方法

forEach() 方法是在 Java 8 中被添加到 java.lang.Iterable 接口的,这意味着所有的集合(List、Set 等)都拥有这个方法。

  • 作用: 为集合中的每个元素执行一次给定的操作。

  • 方法签名: void forEach(Consumer<? super T> action)

  • 参数: 它接受一个 Consumer (消费者) 类型的参数。Consumer 是一个函数式接口,它代表了一个接受单个输入参数并且没有返回值的操作。通俗地讲,它就是“消费”一个元素,然后用这个元素去做一些事情。

3. 核心知识点二:方法引用 (::) 操作符

双冒号 :: 是 Java 8 中引入的方法引用操作符。它是一种用于直接引用已有方法的 Lambda 表达式的简化写法。当 Lambda 表达式的主体只是调用一个已存在的方法时,方法引用可以让代码更加清晰和易读。

让我们来分析 this::enrichModelDetailVo 这个部分:

  • this: 指代当前类的实例对象。

  • ::: 分隔符,用于连接对象/类与方法名。

  • enrichModelDetailVo: 需要被引用的实例方法名。

工作原理:
方法引用 this::enrichModelDetailVo 会被 Java 编译器自动转换成一个实现了 Consumer 接口的实例,而这正好是 forEach 方法所需要的参数类型。

4. 融会贯通:三种等价的代码写法

modelList.forEach(this::enrichModelDetailVo);

代码解读: “对于 modelList 中的每一个元素,都调用当前对象的 enrichModelDetailVo 方法,并将该元素作为参数传进去。”

方法引用本质上是 Lambda 表达式的一种语法。下面的代码在功能上与写法一完全相同。

modelList.forEach(vo -> this.enrichModelDetailVo(vo));

代码解读: “对于 modelList 中的每一个元素(我们临时称之为 vo),执行以下操作:调用 this.enrichModelDetailVo() 方法,并把 vo 作为参数传入。”

for (ModelDetailVo vo : modelList) {this.enrichModelDetailVo(vo);
}

代码解读: “创建一个循环来遍历 modelList。在每一次循环中,将当前元素赋值给变量 vo,然后用 vo 作为参数调用 this.enrichModelDetailVo() 方法。”

5. 使用 forEach 与方法引用的优势

对比维度forEach 与方法引用传统 for 循环
编程风格声明式 (Declarative) - “做什么”命令式 (Imperative) - “怎么做”
代码可读性。意图非常清晰:将一个操作应用于所有元素。。循环的样板代码可能会掩盖其核心操作。
代码简洁性非常高。一行富有表现力的代码即可完成。较低。需要多行代码和循环语法(for, (), {})。
代码表达力。清晰地将数据(modelList)和操作(enrichModelDetailVo)分离开。较低。迭代逻辑和业务操作逻辑耦合在一起。

6. 总结

  • 它是什么: modelList.forEach(this::enrichModelDetailVo); 是一种简洁的函数式循环,它将当前对象的 enrichModelDetailVo 方法应用到了 modelList 的每一个元素上。

  • 何时使用: 当你需要对一个集合的每个元素调用一个已经存在的、单一的方法时,这是最理想的选择。被引用的方法签名必须与所需的函数式接口兼容(forEach 需要的是 Consumer,即接受一个参数,返回 void)。这里的例子中 enrichModelDetailVo 方法虽然有返回值,但 forEach 会忽略它,因此是兼容的。

  • 何时避免: 如果你的循环体逻辑比单个方法调用更复杂(例如,包含多个 if/else 分支、调用多个方法或需要处理异常),那么使用多行 Lambda 表达式 forEach(vo -> { ... }); 或者传统的 for 循环可能会让代码的逻辑更清晰。

http://www.xdnf.cn/news/19710.html

相关文章:

  • CoreShop微信小程序商城框架开启多租户-添加一个WPF客户端以便进行上传产品信息和图片(6)
  • 在本地使用 Docker 创建一个易受攻击的云环境
  • leetcode46.全排列
  • 【LLIE专题】一种语义感知知识引导的低照度图像增强方案
  • Day23 机器学习流水线(管道/pipeline)
  • 小程序开发:懒加载只加载当前和滑动到的图片
  • 【Doris入门】Doris数据表模型:主键模型(Unique Key Model)详解
  • 【重学MySQL】九十六、MySQL SQL Mode高效配置全攻略
  • Linux 孤儿进程 (Orphan Process)
  • 【学Python自动化】 6.1 Python 模块系统学习笔记 (与 Rust 对照)
  • Linux中命令收集
  • UE5 C++ 第三方动态库的使用
  • 「任天堂物语」08 任天堂的山寨时代
  • 递归进阶之全排列、组合
  • JS箭头函数
  • 数字铁流:2025.9.3国庆大阅兵系统架构解析
  • 贪心算法解决固定长度区间覆盖问题:最少区间数计算
  • OpenCV 实战:图像模板匹配与旋转处理实现教程
  • G156HAN04.0 宽温域高亮工业屏技术白皮书
  • Spring Ioc —— 集合类型的依赖注入
  • Next.js渲染模式:SSR、SSG与ISR揭秘
  • 第六章:健壮Go应用:工程实践与生产就绪之测试
  • 旧实例数据库损坏sqlserver启动失败解决办法
  • Java PDF转多种图片格式:技术实践与性能优化
  • CS25FTFR010 1225 0.01R/10mR有哪些优势-华年商城
  • 联邦学习论文分享:Federated Learning via Synthetic Data
  • 搭建APP应用程序如何选择服务器
  • 选择图片转base64格式组件简单封装-Base64ImageInpu
  • 【Node.js教程】Express框架入门:从搭建到动态渲染商品列表
  • 埃文科技亮相2025中部数字经济产业发展大会暨数智创新博览会