
在软件开发中,我们经常会遇到需要对一个对象的多个字段进行非空校验的场景。传统的做法是使用一系列独立的 if 语句来检查每个字段,并在不满足条件时抛出异常。以下是一个典型的示例:
public class User {
private String name;
private String lastName;
private String dni; // 身份证号
private String vehicle;
// 构造函数、Getter和Setter省略
public String getName() { return name; }
public String getLastName() { return lastName; }
public String getDni() { return dni; }
public String getVehicle() { return vehicle; }
}
public class ValidationService {
private void validateUserFields(User user) {
if(user.getName() == null){
throw new RuntimeException("The user's name cannot be null");
}
if(user.getLastName() == null){
throw new RuntimeException("The user's lastName cannot be null");
}
if(user.getDni() == null){
throw new RuntimeException("The user's dni cannot be null");
}
if(user.getVehicle() == null){
throw new RuntimeException("The user's vehicle cannot be null");
}
}
}这种模式虽然直观,但存在明显的缺点:
为了解决上述问题,我们可以利用 Java 8 的函数式编程特性,特别是 Lambda 表达式、Stream API 和 Map 数据结构,将校验逻辑进行抽象和集中管理。核心思想是将每个字段的获取方法(getter)与字段名关联起来,存储在一个 Map 中,然后通过遍历 Map 来执行统一的校验流程。
首先,我们需要创建一个 Map 来存储字段名和对应的 getter 方法引用。Map 的键是字段的字符串名称,值是一个 Function<User, ?> 类型,它表示一个接受 User 对象并返回任意类型(? 通配符)的函数。
import java.util.Map;
import java.util.function.Function;
public class ValidationService {
// 定义一个静态的、不可变的校验规则映射
private static final Map<String, Function<User, ?>> VALIDATIONS = Map.of(
"name", User::getName,
"lastName", User::getLastName,
"dni", User::getDni,
"vehicle", User::getVehicle
);
// ... 后续的校验方法
}这里使用了 Map.of() 方法,它是 Java 9 引入的用于创建不可变 Map 的便捷方法。如果您的项目仍在使用 Java 8,可以使用 Collections.unmodifiableMap() 配合 new HashMap<>() 来实现。
立即学习“Java免费学习笔记(深入)”;
有了校验规则映射 VALIDATIONS,我们就可以编写一个高度抽象和可扩展的校验方法。
方案一:详细的 Stream 管道
public class ValidationService {
// ... VALIDATIONS Map 定义
private void validateUserFields(User user) {
VALIDATIONS.entrySet().stream() // 获取Map的Entry集合并转换为Stream
.filter(entry -> entry.getValue().apply(user) == null) // 过滤出值为null的字段
.map(Map.Entry::getKey) // 提取字段名
.map(field -> String.format("The user's %s cannot be null", field)) // 格式化错误消息
.map(RuntimeException::new) // 将错误消息转换为RuntimeException对象
.findFirst() // 找到第一个不满足条件的字段(即第一个错误)
.ifPresent(e -> { // 如果存在错误,则抛出异常
throw e;
});
}
}代码解析:
方案二:更简洁的 Stream 管道
如果你觉得方案一的 map 操作链条过长,可以在 ifPresent 中直接构建异常信息:
public class ValidationService {
// ... VALIDATIONS Map 定义
private void validateUserFields(User user) {
VALIDATIONS.entrySet().stream()
.filter(entry -> entry.getValue().apply(user) == null)
.findFirst() // 找到第一个不满足条件的Map.Entry
.ifPresent(e -> { // 如果存在错误,则抛出异常
throw new RuntimeException("The user's " + e.getKey() + " cannot be null");
});
}
}这个版本直接在 ifPresent 中通过 e.getKey() 获取字段名并构造异常消息,减少了中间的 map 操作,使得代码更为紧凑。
通过将传统的冗余 if 语句重构为基于 Java 8 Lambda、Stream API 和 Map 的校验模式,我们不仅极大地提升了代码的简洁性、可读性和可扩展性,还使得校验逻辑更加集中和易于维护。这种模式是现代 Java 开发中优化代码结构、提升开发效率的有效实践,尤其适用于需要对多个相似属性进行统一处理的场景。掌握并灵活运用这些函数式编程特性,将有助于编写出更优雅、更健壮的应用程序。
以上就是Java 8 Lambda 与 Map:重构冗余 if 语句的实践指南的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号