0Pricing
Java Academy · 课时

使用 thenApply 和 thenCompose 链式处理

使用 thenApply 转换结果,并通过 thenCompose 将异步步骤与 flatMap 链接,避免嵌套 Future

使用 thenApply 和 thenCompose 链式处理 是 CoddyKit 上的免费 Java Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Java Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Java Academy 课程共包含 4 节课。

thenApply:转换结果

thenApply(Function) 会对已完成 future 的结果应用同步函数,并返回一个包含转换后类型的新 future。它不会启动新的异步任务。

CompletableFuture<String> nameFuture = CompletableFuture
    .supplyAsync(() -> 42L)            // CF<Long>
    .thenApply(id -> "User#" + id);    // CF<String>
System.out.println(nameFuture.join()); // "User#42"

thenApplyAsync:在线程中进行转换

thenApplyAsync 会在 ForkJoinPool(或所提供的执行器)中运行转换函数,使完成原 future 的线程能够立即释放。

CompletableFuture<String> result = fetchUserAsync()
    .thenApplyAsync(user -> serialize(user)); // runs on pool thread

thenAccept:处理结果但不返回值

thenAccept(Consumer) 会处理结果,但返回 CompletableFuture<Void>。当您不需要继续传递值时,可以将它用作流程的最后一步。

fetchUserAsync()
    .thenApply(User::getName)
    .thenAccept(name -> System.out.println("Hello, " + name));

thenRun:完成后运行

thenRun(Runnable) 会在 future 完成后运行任务,并忽略结果。它适合用于关闭资源或触发副作用。

downloadFileAsync(url)
    .thenRun(() -> System.out.println("Download complete"));

串联多个 thenApply 调用

多个 thenApply 调用会形成一个流程。每一步都会接收上一步的输出。

CompletableFuture<Double> result = CompletableFuture
    .supplyAsync(() -> "  42.5  ")
    .thenApply(String::trim)
    .thenApply(Double::parseDouble)
    .thenApply(d -> d * 1.21); // apply 21% VAT
System.out.println(result.join()); // 51.425

thenCompose:展平嵌套 Future

thenCompose(Function<T, CompletionStage<U>>) 类似于 future 的 flatMap。它通过展平嵌套 future,避免产生 CompletableFuture<CompletableFuture<T>>。

// Wrong with thenApply — returns CF<CF<Order>>:
CompletableFuture<CompletableFuture<Order>> nested =
    fetchUser(id).thenApply(u -> fetchLatestOrder(u.getId()));
// Correct with thenCompose — returns CF<Order>:
CompletableFuture<Order> flat =
    fetchUser(id).thenCompose(u -> fetchLatestOrder(u.getId()));

使用 thenCompose 进行顺序异步调用

当每个异步步骤都依赖上一步的结果时,请使用 thenCompose,这样可以使各步骤按顺序执行,并依赖相应结果。

fetchUser(userId)
    .thenCompose(user -> fetchOrders(user.getId()))
    .thenCompose(orders -> computeTotal(orders))
    .thenAccept(total -> System.out.println("Total: " + total));

thenApply 与 thenCompose

thenApply:将 T -> U 映射为同步转换。thenCompose:将 T -> CompletableFuture<U> 映射并展平。当下一步同样是异步操作时,请使用 compose。

使用 handle 处理中间错误

无论 future 正常完成还是异常完成,都会调用 handle(BiFunction<T, Throwable, U>),因此您可以在流程中途恢复或转换错误。

fetchUser(id)
    .thenApply(User::getProfile)
    .handle((profile, ex) -> {
        if (ex != null) return Profile.empty(); // recover
        return profile;
    })
    .thenAccept(System.out::println);

whenComplete:在任何结果之后执行副作用

完成后(无论正常还是异常),都会调用 whenComplete(BiConsumer),用于日志记录或清理。与 handle 不同,它不会改变结果。

fetchAsync()
    .whenComplete((result, ex) -> {
        if (ex != null) log.error("Failed", ex);
        else            log.info("Result: " + result);
    });

非阻塞流程示例

请组合一个完全非阻塞的流程:获取用户,获取该用户的订单,然后计算摘要。所有步骤都会异步运行,并且每一步都依赖上一步。

CompletableFuture<String> summary =
    fetchUser(userId)
        .thenCompose(u -> fetchOrders(u.getId()))
        .thenApply(orders -> orders.size() + " orders")
        .exceptionally(ex -> "Error: " + ex.getMessage());
System.out.println(summary.join());

快速检查

什么时候应该使用 thenCompose,而不是 thenApply?

回顾

thenApply 会在流程中转换同步值。thenCompose 会串联异步步骤(相当于 future 的 flatMap)。handle / whenComplete 用于添加错误处理和副作用。请从左到右构建流程,以提高可读性。

常见问题解答

「使用 thenApply 和 thenCompose 链式处理」课时是免费的吗?

是的 — 「使用 thenApply 和 thenCompose 链式处理」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Java Academy 课程的其余内容,请升级到 CoddyKit PRO。 Java Academy 课程共包含 4 节课。

「使用 thenApply 和 thenCompose 链式处理」这节课中我会学到什么?

使用 thenApply 转换结果,并通过 thenCompose 将异步步骤与 flatMap 链接,避免嵌套 Future 你通过在浏览器中直接运行的动手代码来练习 Java Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Java Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Java Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。

「使用 thenApply 和 thenCompose 链式处理」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Java Academy 课中编写并运行代码吗?

能。每节 Java Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 创建和完成 CompletableFutures
  2. 使用 thenApply 和 thenCompose 链式处理
  3. 组合 Future:allOf 与 anyOf
  4. 错误处理与异步 HTTP 流水线
← 返回 Java Academy