CompletableFuture的thenCompose和thenApply有什么区别?

CompletableFuturethenComposethenApply 方法都是用来处理异步计算结果的,但它们在处理方式上有很重要的区别。

1.区别

  1. thenApply thenApply 用于将前一个异步计算的结果进行转换。你提供一个函数,这个函数接受前一个计算的结果作为输入,并返回一个新的值。这个方法不会创建另一个CompletableFuture,它只是返回一个将计算结果应用函数后的新CompletableFuture

    使用 thenApply 的例子:

    ini 复制代码
    CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello");
    CompletableFuture<String> greetingFuture = future.thenApply(s -> s + " World!");
    // greetingFuture 完成时会得到 "Hello World!"
  2. thenCompose thenCompose 用于链接两个异步操作,当第一个操作完成时,将其结果作为参数传递给一个返回CompletableFuture的函数。这使得你可以创建一个平坦的结果链,即只有一个级别的CompletableFuture,而不是嵌套的CompletableFuture<CompletableFuture<T>>

    使用 thenCompose 的例子:

    ini 复制代码
    CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello");
    CompletableFuture<String> greetingFuture = future.thenCompose(s -> CompletableFuture.supplyAsync(() -> s + " World!"));
    // greetingFuture 完成时会得到 "Hello World!"

简单来说,thenApply 类似于 map 操作,用于对结果进行映射;而 thenCompose 类似于 flatMap 操作,用于链接多个异步操作,避免嵌套的 CompletableFuture 结构。

这两个方法对于处理异步操作链中的不同阶段非常有用,选择哪个方法取决于你的具体需求: 是否需要进行异步操作链接(compose),或者仅仅需要对结果进行转换(apply)。

2.案例

假设我们有一个在线书店,我们需要首先根据用户的ID异步获取用户信息,然后再根据用户信息异步获取推荐的书籍列表。

使用 thenApply(映射结果)

typescript 复制代码
   import java.util.concurrent.CompletableFuture;

   public class BookStore {

   // 模拟异步获取用户信息
   public CompletableFuture<User> getUserInfo(String userId) {
       return CompletableFuture.supplyAsync(() -> {
           // 模拟从数据库或远程服务获取用户信息
           return new User(userId, "John Doe");
       });
   }

   // 模拟同步获取推荐书籍列表
   public List<Book> getRecommendedBooks(User user) {
       // 根据用户信息同步获取推荐书籍
       return Arrays.asList(new Book("Book1"), new Book("Book2"));
   }

   public void displayRecommendedBooks(String userId) {
       CompletableFuture<List<Book>> recommendedBooksFuture = getUserInfo(userId)
               .thenApply(user -> getRecommendedBooks(user)); // 使用 thenApply 对结果进行映射

       recommendedBooksFuture.thenAccept(books -> books.forEach(book -> System.out.println(book.getTitle())));
   }
 }

在这个例子中,thenApply 使用了从getUserInfo方法返回的User对象,并同步地调用了getRecommendedBooks方法来得到书籍列表。由于getRecommendedBooks方法是同步的,这里不会引入额外的异步操作。

使用 thenCompose(链接异步操作)

现在假设getRecommendedBooks也是一个异步操作,我们需要修改我们的方法来适应这一点。

typescript 复制代码
import java.util.concurrent.CompletableFuture;

public class BookStore {

    // 模拟异步获取用户信息
    public CompletableFuture<User> getUserInfo(String userId) {
        return CompletableFuture.supplyAsync(() -> {
            // 模拟从数据库或远程服务获取用户信息
            return new User(userId, "John Doe");
        });
    }

    // 现在异步获取推荐书籍列表
    public CompletableFuture<List<Book>> getRecommendedBooksAsync(User user) {
        return CompletableFuture.supplyAsync(() -> {
            // 模拟异步获取推荐书籍
            return Arrays.asList(new Book("Book1"), new Book("Book2"));
        });
    }

    public void displayRecommendedBooks(String userId) {
        CompletableFuture<List<Book>> recommendedBooksFuture = getUserInfo(userId)
                .thenCompose(user -> getRecommendedBooksAsync(user)); // 使用 thenCompose 链接另一个异步操作

        recommendedBooksFuture.thenAccept(books -> books.forEach(book -> System.out.println(book.getTitle())));
    }
}

在这个修改后的例子中,我们使用thenCompose来链接两个异步操作:首先异步获取用户信息,然后在用户信息获取后,我们传递它到getRecommendedBooksAsync方法异步获取书籍列表。thenCompose确保我们有一个平坦的、不嵌套的CompletableFuture<List<Book>>,我们可以在其上注册一个动作来处理最终的推荐书籍列表。

通过这两个例子,你应该能够看到thenApplythenCompose在实际应用中的区别:thenApply适用于同步结果转换,而thenCompose适用于链接多个异步操作。

相关推荐
野犬寒鸦6 小时前
从零起步学习并发编程 || 第一章:初步认识进程与线程
java·服务器·后端·学习
我爱娃哈哈6 小时前
SpringBoot + Flowable + 自定义节点:可视化工作流引擎,支持请假、报销、审批全场景
java·spring boot·后端
李梨同学丶8 小时前
0201好虫子周刊
后端
思想在飞肢体在追8 小时前
Springboot项目配置Nacos
java·spring boot·后端·nacos
Loo国昌11 小时前
【垂类模型数据工程】第四阶段:高性能 Embedding 实战:从双编码器架构到 InfoNCE 损失函数详解
人工智能·后端·深度学习·自然语言处理·架构·transformer·embedding
ONE_PUNCH_Ge11 小时前
Go 语言泛型
开发语言·后端·golang
良许Linux12 小时前
DSP的选型和应用
后端·stm32·单片机·程序员·嵌入式
不光头强12 小时前
spring boot项目欢迎页设置方式
java·spring boot·后端
怪兽毕设12 小时前
基于SpringBoot的选课调查系统
java·vue.js·spring boot·后端·node.js·选课调查系统
学IT的周星星12 小时前
Spring Boot Web 开发实战:第二天,从零搭个“会卖萌”的小项目
spring boot·后端·tomcat