面试题答案
一键面试功能区别
- thenApply:
- 功能:接收一个异步计算的结果,将其作为参数传递给一个Function,返回一个新的CompletableFuture,该CompletableFuture的结果是Function应用后的返回值。它适用于对单个异步任务的结果进行转换。
- 示例:
CompletableFuture.supplyAsync(() -> "Hello") .thenApply(s -> s + " World");
- thenCombine:
- 功能:等待两个CompletableFuture都完成,然后将两个结果作为参数传递给一个BiFunction,返回一个新的CompletableFuture,其结果是BiFunction应用后的返回值。它用于合并两个异步任务的结果。
- 示例:
CompletableFuture.supplyAsync(() -> 5) .thenCombine(CompletableFuture.supplyAsync(() -> 3), (a, b) -> a + b);
- thenCompose:
- 功能:接收一个异步计算的结果,将其作为参数传递给一个函数,该函数返回一个新的CompletableFuture。它的关键在于能将嵌套的CompletableFuture扁平化,适用于异步任务的链式调用,其中每个任务的结果作为下一个任务的输入。
- 示例:
CompletableFuture.supplyAsync(() -> "Hello") .thenCompose(s -> CompletableFuture.supplyAsync(() -> s + " World"));
适用场景区别
- thenApply:当需要对单个异步任务的结果进行简单转换时使用,例如数据格式转换、数据映射等。
- thenCombine:当需要将两个独立的异步任务的结果合并为一个结果时使用,比如从两个不同数据源获取数据后进行合并处理。
- thenCompose:当有一系列异步任务,每个任务依赖前一个任务的结果时使用,例如在微服务架构中,一个服务的输出作为另一个服务的输入进行链式调用。
复杂场景下的优化代码示例
假设我们有三个服务调用,第一个服务获取用户ID,第二个服务根据用户ID获取用户信息,第三个服务根据用户信息进行一些复杂的条件判断和数据处理。
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
public class CompletableFutureExample {
// 模拟第一个服务调用,获取用户ID
private static CompletableFuture<Integer> getUserID() {
return CompletableFuture.supplyAsync(() -> {
// 模拟一些延迟操作
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 1;
});
}
// 模拟第二个服务调用,根据用户ID获取用户信息
private static CompletableFuture<String> getUserInfo(int userId) {
return CompletableFuture.supplyAsync(() -> {
// 模拟一些延迟操作
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "User with ID " + userId;
});
}
// 模拟第三个服务调用,根据用户信息进行复杂处理
private static CompletableFuture<String> processUserInfo(String userInfo) {
return CompletableFuture.supplyAsync(() -> {
// 模拟一些延迟操作
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (userInfo.contains("1")) {
return userInfo + " processed successfully";
} else {
return "Error processing user";
}
});
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
CompletableFuture<String> result = getUserID()
.thenCompose(CompletableFutureExample::getUserInfo)
.thenCompose(CompletableFutureExample::processUserInfo);
System.out.println(result.get());
}
}
在这个示例中,使用thenCompose
方法能清晰地表达任务之间的依赖关系,使代码具有良好的可读性,同时利用异步特性提高了性能。如果使用thenApply
或thenCombine
,代码逻辑会变得复杂且难以维护,因为它们不适合这种链式依赖的异步任务场景。