You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现类似CompletableFuture.anyOf()但返回首个非null结果的功能?

如何实现类似CompletableFuture.anyOf()但返回首个非null结果的功能?

当然可以做到!我来给你分享一个实用的实现思路和代码示例:

核心思路其实很简单:CompletableFuture.anyOf()会响应第一个完成的future,不管结果是不是null。那我们只需要给每个原始的future做一层“包装”——让它们只有在返回非null结果时才会“完成”,如果返回null,就让这个包装后的future暂时处于未完成状态,这样它就不会被anyOf()选中。

第一步:写一个工具方法包装原始Future

我们可以封装一个方法,把每个原始Future转换成符合要求的新Future:

private static <T> CompletableFuture<T> wrapNonNullFuture(CompletableFuture<T> originalFuture) {
    return originalFuture.thenCompose(result -> {
        // 如果结果非null,直接用这个结果完成新Future
        if (result != null) {
            return CompletableFuture.completedFuture(result);
        } else {
            // 如果结果是null,返回一个永远不会主动完成的Future
            // 这样它就不会被后续的anyOf()选中
            return new CompletableFuture<>();
        }
    });
}

第二步:包装所有Future并调用anyOf()

接下来把你所有的原始Future都用这个方法包装一遍,再传给anyOf(),这样得到的就是第一个返回非null结果的Future了:

// 你的原始Future列表
CompletableFuture<String> comp1 = CompletableFuture.supplyAsync(() -> {
    // 模拟可能返回null的业务逻辑
    return Math.random() > 0.5 ? "来自Comp1的有效结果" : null;
});
CompletableFuture<String> comp2 = CompletableFuture.supplyAsync(() -> {
    return Math.random() > 0.5 ? "来自Comp2的有效结果" : null;
});
// 可以添加更多comp3、comp4...

// 包装所有原始Future
CompletableFuture<?>[] nonNullFutures = Stream.of(comp1, comp2)
        .map(YourClassName::wrapNonNullFuture)
        .toArray(CompletableFuture<?>[]::new);

// 现在调用anyOf(),拿到的就是首个非null的结果
CompletableFuture<Object> firstNonNullResult = CompletableFuture.anyOf(nonNullFutures);

额外补充:处理极端情况

如果所有原始Future都返回null,那上面的firstNonNullResult会一直处于未完成状态,这显然不太友好。我们可以给它加个超时处理,避免无限等待:

CompletableFuture<Object> resultWithTimeout = CompletableFuture.anyOf(nonNullFutures)
        .orTimeout(5, TimeUnit.SECONDS) // 5秒超时
        .exceptionally(ex -> {
            // 超时或其他异常时的兜底处理,比如返回默认值
            return "默认兜底结果";
        });

另外,如果你的原始Future可能抛出异常,还可以在包装方法里加上异常处理,把异常也当成“无效结果”(即null)来处理:

private static <T> CompletableFuture<T> wrapNonNullFutureWithExceptionHandling(CompletableFuture<T> originalFuture) {
    return originalFuture.handle((result, exception) -> {
        // 如果有异常,直接返回null,后续逻辑会把它当成无效结果
        if (exception != null) {
            return null;
        }
        return result;
    }).thenCompose(result -> {
        if (result != null) {
            return CompletableFuture.completedFuture(result);
        } else {
            return new CompletableFuture<>();
        }
    });
}

这样调整后,不管是返回null还是抛出异常的Future,都不会干扰我们获取第一个有效(非null)的结果啦。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.07 08:24:33