执行器工具
框架在 host.springboot.framework3.core.execute 包下提供了两个实用工具类:
MapExecutor:专为复杂嵌套 Map 设计,简化多层级数据结构的操作ObjectExecutor:条件执行器,减少业务代码中的 null 判断和条件分支
本文档侧重介绍 MapExecutor 的应用场景与最佳实践。
MapExecutor - 嵌套 Map 操作利器
在实际开发中,经常会遇到复杂的嵌套 Map 数据结构,例如:
Map<String, List<User>>:按部门分组的用户列表Map<String, Map<String, Integer>>:多维度统计数据Map<Long, Map<String, List<Order>>>:用户订单分组
传统写法需要大量 null 判断和临时变量,而 MapExecutor 提供了一套优雅的 API 来简化这些操作。
核心方法速览
| 方法 | 功能 | 适用数据结构 |
|---|---|---|
dynamicPut | 向嵌套集合/Map 添加单个元素 | Map<K, Collection> / Map<K, Map> |
dynamicPutAll | 向嵌套集合批量添加元素 | Map<K, Collection> / Map<K, Map<K, Collection>> |
dynamicGet | 从嵌套 Map 中获取值 | Map<K, Map<K, V>> |
dynamicIncrement | 递增嵌套 Map 中的计数器 | Map<K, Integer> / Map<K, Map<K, Integer>> |
dynamicDecrement | 递减嵌套 Map 中的计数器 | Map<K, Integer> / Map<K, Map<K, Integer>> |
dynamicOffset | 对嵌套 Map 中的数值进行偏移 | Map<K, Integer> / Map<K, Map<K, Integer>> |
dynamicExecute | 自定义条件执行逻辑 | 任意 Map<K, V> |
使用场景与示例
场景1:按分组收集数据 - Map<K, List<V>>
业务需求:将用户列表按部门分组
❌ 传统写法
java
Map<String, List<User>> usersByDept = new HashMap<>();
for (User user : users) {
String dept = user.getDepartment();
// 每次都要判断 null 并手动创建 List
List<User> list = usersByDept.get(dept);
if (list == null) {
list = new ArrayList<>();
usersByDept.put(dept, list);
}
list.add(user);
}✅ 使用 MapExecutor
java
Map<String, List<User>> usersByDept = new HashMap<>();
for (User user : users) {
MapExecutor.dynamicPut(
usersByDept, // 目标 Map
user.getDepartment(), // 外层 key
user, // 要添加的元素
ArrayList::new // 当 List 不存在时创建新的
);
}优势:
- 🚀 一行代码完成判断 + 创建 + 添加
- 🧹 消除重复的 null 检查逻辑
- 📖 代码意图更清晰
场景2:多维度统计 - Map<K, Map<K, Integer>>
业务需求:统计每个部门各个岗位的人数
❌ 传统写法
java
Map<String, Map<String, Integer>> deptJobCount = new HashMap<>();
for (User user : users) {
String dept = user.getDepartment();
String job = user.getJob();
Map<String, Integer> jobCountMap = deptJobCount.get(dept);
if (jobCountMap == null) {
jobCountMap = new HashMap<>();
deptJobCount.put(dept, jobCountMap);
}
Integer count = jobCountMap.get(job);
if (count == null) {
count = 0;
}
jobCountMap.put(job, count + 1);
}✅ 使用 MapExecutor
java
Map<String, Map<String, Integer>> deptJobCount = new HashMap<>();
for (User user : users) {
MapExecutor.dynamicIncrement(
deptJobCount, // 目标 Map
user.getDepartment(), // 外层 key(部门)
user.getJob(), // 内层 key(岗位)
HashMap::new // 当内层 Map 不存在时创建
);
}优势:
- 🎯 自动处理两层嵌套的 null 初始化
- 📊 递增逻辑封装在方法内部,无需手动 +1
场景3:三层嵌套 - Map<K, Map<K, List<V>>>
业务需求:按用户 ID 和订单状态分组订单
✅ 使用 MapExecutor
java
Map<Long, Map<String, List<Order>>> orderMap = new HashMap<>();
for (Order order : orders) {
MapExecutor.dynamicPut(
orderMap, // 目标 Map
order.getUserId(), // 外层 key(用户ID)
order.getStatus(), // 内层 key(订单状态)
order, // 要添加的订单
HashMap::new, // 内层 Map 不存在时创建
ArrayList::new // List 不存在时创建
);
}输出数据结构:
json
{
"1001": {
"PENDING": [Order(...), Order(...)],
"COMPLETED": [Order(...)]
},
"1002": {
"PENDING": [Order(...)],
"CANCELLED": [Order(...)]
}
}场景4:批量添加 - dynamicPutAll
业务需求:将多个订单批量添加到用户订单分组中
java
Map<Long, List<Order>> userOrders = new HashMap<>();
List<Order> newOrders = Arrays.asList(order1, order2, order3);
MapExecutor.dynamicPutAll(
userOrders, // 目标 Map
userId, // 用户ID
newOrders, // 要批量添加的订单列表
ArrayList::new // 当 List 不存在时创建
);场景5:递减与自定义偏移
递减计数器:
java
Map<String, Integer> inventory = new HashMap<>();
inventory.put("iPhone", 100);
// 每次销售递减库存
MapExecutor.dynamicDecrement(inventory, "iPhone");
// inventory.get("iPhone") -> 99自定义偏移量:
java
// 批量销售 10 台
MapExecutor.dynamicOffset(inventory, "iPhone", -10);
// inventory.get("iPhone") -> 89
// 补货 50 台
MapExecutor.dynamicOffset(inventory, "iPhone", 50);
// inventory.get("iPhone") -> 139场景6:条件执行 - dynamicExecute
业务需求:只有当值满足条件时才执行自定义逻辑
java
Map<String, Integer> scores = new HashMap<>();
// 只有分数 >= 60 时才记录
MapExecutor.dynamicExecute(
scores, // 目标 Map
"math", // key
85, // 新分数
score -> score >= 60, // 条件:及格才记录
(newScore, oldScore) -> { // 自定义逻辑:取最高分
return oldScore == null ? newScore : Math.max(newScore, oldScore);
},
() -> 0 // 初始值为 0
);ObjectExecutor - 条件执行简化器
ObjectExecutor 提供了一组条件执行方法,减少业务代码中的 if 判断。
核心方法
| 方法 | 功能 | 适用场景 |
|---|---|---|
execute | 条件为 true 时执行 | 布尔条件判断 |
notNullExecute | 对象非 null 时执行 | null 安全检查 |
notBlankExecute | 字符串非空时执行 | 字符串校验 |
notEmptyExecute | 集合非空时执行 | 集合校验 |
使用示例
传统 if 判断
java
if (user != null) {
log.info("用户名: {}", user.getName());
}
if (StringUtils.isNotBlank(remark)) {
order.setRemark(remark);
}
if (CollectionUtils.isNotEmpty(tags)) {
product.setTags(tags);
}使用 ObjectExecutor
java
ObjectExecutor.notNullExecute(user, flag ->
log.info("用户名: {}", user.getName())
);
ObjectExecutor.notBlankExecute(remark, flag ->
order.setRemark(remark)
);
ObjectExecutor.notEmptyExecute(tags, flag ->
product.setTags(tags)
);最佳实践
✅ 推荐做法
使用
MapExecutor处理嵌套 Map- 代替繁琐的 null 判断和手动初始化
- 提高代码可读性和维护性
使用方法引用传递构造函数
javaArrayList::new, HashMap::new, HashSet::new统计类场景优先使用
dynamicIncrement/Decrement- 自动处理 null 初始化为 0
批量操作使用
dynamicPutAll- 减少循环次数
❌ 不推荐做法
- ❌ 过度使用导致代码逻辑不清晰
- ❌ 在简单场景使用,反而增加理解成本
- ❌ 忽略类型安全,使用
Map<Object, Object>这种宽泛定义
常见问题 FAQ
Q: MapExecutor 是线程安全的吗?
A: MapExecutor 本身是无状态的工具类,线程安全。但它操作的 Map 对象的线程安全性取决于你传入的具体实现(如 HashMap 非线程安全,ConcurrentHashMap 线程安全)。
Q: 什么时候使用 MapExecutor,什么时候用 Stream API?
A:
- MapExecutor:适合需要"边遍历边分组/统计"的场景,实时更新数据结构
- Stream API:适合"先处理后收集"的场景,例如
Collectors.groupingBy()
Q: ObjectExecutor 与传统 if 判断有什么区别?
A:
- ObjectExecutor 更适合链式调用、函数式编程风格
- 传统 if 更直观,适合复杂条件分支
- 选择取决于团队编码风格与场景复杂度
Q: 为什么需要传递 Supplier 来创建集合?
A: 因为 MapExecutor 不知道你想创建 ArrayList、LinkedList 还是 HashSet。通过 Supplier,你可以灵活指定具体实现类型,保持类型安全。
