lambda表达式滥用之殇:解耦三层嵌套lambda表达式
自从 Java8 支持 lambda 表达式, 代码中的 lambda 就到处都是。 但大多是滥用。
lambda 表达式用于表达简短的逻辑(可以看做 C 语言的内联函数)非常清晰,但用来表达比较长的业务逻辑,就与其设计初衷背道而驰了。
如下所示,三层嵌套 lambda 表达式,晕了没有 ?
如何解开这些结呢 ? 一步步来。
首先, allImageIds.forEach 是一个明显的 Stream-add 模式,可以使用 stream.map 来表达:
List<CompletableFuture<String>> completableFutureList
= allImageIds.stream().map(imageId -> buildCompletableFuture(imageId, comId, newGroup)).collect(Collectors.toList());
private CompletableFuture<String> buildCompletableFuture(String imageId, String comId, int newGroup) {
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
String lockKey = String.format("%s%s%s", comId, newGroup, imageId);
return redisLock.call(lockKey, () -> {
return dealWith(comId, newGroup, imageId);
});
}, executorService);
return future;
}
这样,就解耦了一层。
接下来,CompletableFuture.supplyAsync 需要提供一个 Supplier
private CompletableFuture<String> buildCompletableFuture(String imageId, String comId, int newGroup) {
Supplier<String> futureSupplier = () -> {
String lockKey = String.format("%s%s%s", comId, newGroup, imageId);
return redisLock.call(lockKey, () -> {
return dealWith(comId, newGroup, imageId);
});
};
CompletableFuture<String> future = CompletableFuture.supplyAsync(futureSupplier, executorService);
return future;
}
这样,我们又让结构清晰了一些。
最后,我们把 redisLock.call 里面的 lambda 表达式分离出来。 这个 lambda 表达式代表的是 ValueLockCallback 接口。 可以把这个表达式变成一个内部类(还原) ImageIdValueCallback :
private CompletableFuture<String> buildCompletableFuture(String imageId, String comId, int newGroup) {
Supplier<String> futureSupplier = () -> {
String lockKey = String.format("%s%s%s", comId, newGroup, imageId);
return redisLock.call(lockKey, new ImageIdValueCallback(imageId, comId, newGroup));
};
CompletableFuture<String> future = CompletableFuture.supplyAsync(futureSupplier, executorService);
return future;
}
class ImageIdValueCallback implements ValueLockCallback<String> {
private String imageId;
private String comId;
private int newGroup;
public ImageIdValueCallback(String imageId, String comId, int newGroup) {
this.imageId = imageId;
this.comId = comId;
this.newGroup = newGroup;
}
@Override
public String execute() {
return dealWith(comId, newGroup, imageId); // dealWith 是 redisLock.call 里面的 lambda 表达式里的代码块。
}
}
这样,是不是清晰很多了 ?
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
2017-04-10 编程漫谈(十三):设立挑战和奖励让编程更有趣