在日常开发中,我们会遇到一些代码重复度高、逻辑结构雷同的场景,比如:
- 针对多个字段做相似的判空判断
- 对多个字段的数值格式进行统一处理
- 动态构造 vo 或 dto 列表
以前这些逻辑通常依赖大量 if-else,导致代码冗长、可读性差。随着 java 8 lambda 的流行,我们可以借助 function 函数式接口 让代码更简洁、更易维护。
本文通过一个实际场景,讲解:
- function 是什么
- apply 方法的作用
- 在实际业务里如何利用 function 简化重复逻辑
- 更多 function 的高级用法
🧩 一、function 是什么?
java 8 提供了大量函数式接口(位于 java.util.function 包里),其中 function<t, r> 是最常用的一个:

简单理解:
function 表示一个“输入一个参数(t),输出一个结果(r)”的函数。
例如:
- 输入是
string,输出是integer - 输入是一个实体对象,输出是某个字段的值
- 输入是一个可能为 null 的字段,输出是安全值
🧲 二、apply 做什么?
apply() 是 function 的核心方法,用来执行函数逻辑,你可以把 apply() 理解成“执行这个函数”。比如如下方法,我们需要获取每个字符串的字符串长度:
function<string, integer> lengthfunc = str -> str.length();
int len = lengthfunc.apply("hello"); // 返回 5
📘 三、业务场景:字段多、判空多、逻辑重复
💡1、传统做法
假设我们有一个实体(例如某企业的年度指标数据):
class indicatorentity {
private string amounta;
private string amountb;
private string amountc;
// ...getter/setter
}
我们需要根据它生成一个 vo 列表,输出时存在各种问题,比如
- 字段可能为 null
- 字段可能为空字符串
- 需要统一格式化为两位小数
- 需要填充默认值 “0”……
传统写法会有大量的 if-else 判断,大量重复(下述代码中 format() 表示规范字段的值,如实现判空、保留两位小数等逻辑):
list<itemvo> list = new arraylist<>();
if (stringutils.isnotblank(entity.getamounta())) {
list.add(new itemvo("指标a", format(entity.getamounta()), "吨"));
} else {
list.add(new itemvo("指标a", "0", "吨"));
}
if (stringutils.isnotblank(entity.getamountb())) {
list.add(new itemvo("指标b", format(entity.getamountb()), "吨"));
} else {
list.add(new itemvo("指标b", "0", "吨"));
}
// ...重复更多💡2、使用 function 优化:统一 null 处理与格式化
我们使用一个 function<string, string>,用于将字段安全地转换成非空:
function<string, string> safeformat = val -> val == null ? "" : val;
之后构造字段数组如下:
object[][] fields = {
{"指标a", safeformat.apply(entity.getamounta()), "吨"},
{"指标b", safeformat.apply(entity.getamountb()), "吨"},
{"指标c", safeformat.apply(entity.getamountc()), "吨"},
// 其他指标依次添加
};
之后对其统一格式化处理:
list<itemvo> result = new arraylist<>();
for (object[] field : fields) {
string name = (string) field[0];
string rawvalue = (string) field[1];
string unit = (string) field[2];
string formattedvalue = "0";
if (stringutils.isnotblank(rawvalue)) {
try {
// 统一格式化,例如 numberutil.formatstr(),或其他你需要对字符串进行的操作
formattedvalue = format(rawvalue);
} catch (exception ignored) {
// 你需要进行的异常操作
}
}
result.add(new itemvo(name, formattedvalue, unit));
}经过优化后:
- 重复逻辑消失
- 判空与格式化集中处理
- 字段配置化,易维护
- 添加新字段只需改一个数组,便于之后添加字段到处添加 if-else,修改方便。
🎯 四、function 的实际适用场景总结
① null 安全处理(最常见)
② 字段提取器(getter 复用)——比如多字段统一处理,适用于:动态抽取实体字段值、在工具类中避免大量重复 getter 调用:
<t, r> r getvalue(t entity, function<t, r> getter) {
return getter.apply(entity);
}
string value = getvalue(entity, indicatorentity::getamounta);③ 通用格式化处理——例如统一格式化数字、日期:
function<string, string> formatamount = s -> {
if (stringutils.isblank(s)) return "0";
return numberutil.formatstr(s, 2);
};
④ 配置化字段处理
如本文案例,将字段名称、原始值、单位放在数组或列表中,之后统一判空、格式化、填充默认值、构造vo。
🧨 五、进一步延申:组合函数 compose 与 andthen
compose:先执行参数里的 function,再执行当前 function
function<string, integer> length = s -> s.length();
function<string, string> trim = s -> s.trim();
int len = length.compose(trim).apply(" hi "); // 2andthen:先执行当前 function,再执行参数里的 function
int len = trim.andthen(length).apply(" hi "); // 2
适用于多步骤处理,例如:
- 先判空 → 再格式化
- 先 trim → 再校验
到此这篇关于java 中 function 与 apply 的实际应用场景分析(含优化前后案例)的文章就介绍到这了,更多相关java function 与 apply用法内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论