如何将一种类型的 CompletableFuture 转换为另一种类型?

How do you transform a CompletableFuture of one type to another?

我目前将 CompletableFuture<X> 转换为 CompletableFuture<Void>,如下所示,但我想知道是否有更好的方法。

@Override
public CompletableFuture<Void> packetEncrypted(ByteBuffer engineToSocketData) {
    return realChannel.write(engineToSocketData).thenApply(c -> empty());
}

public Void empty() {
    return null;
}

您实际上是在尝试将 CompletableFuture 的完整值转换为 Void 类型的值。如果那个未来异常完成,大概你想传播任何异常。

CompletableFuture 提供了thenApply 用于此基本转换,但也可以使用其他方法。

在您的情况下,您将希望忽略源 future 和 return null 的值,因为 null 是类型 [=16] 的唯一可能值=].但是,编译器需要一些提示,表明您的目标类型是 Void.

通过为 thenApply

的调用提供显式类型参数来显式
public CompletableFuture<Void> packetEncrypted(ByteBuffer engineToSocketData) {
    return realChannel.write(engineToSocketData).<Void> thenApply(c -> null);
}

或者通过转换为 lambda 表达式中的适当类型来显式

public CompletableFuture<Void> packetEncrypted(ByteBuffer engineToSocketData) {
    return realChannel.write(engineToSocketData).thenApply(c -> (Void) null);
}

您的解决方案实现了相同的结果,因为已知值的类型是正确的,但它涉及额外的方法调用

@Override
public CompletableFuture<Void> packetEncrypted(ByteBuffer engineToSocketData) {
    return realChannel.write(engineToSocketData).thenApply(c -> empty());
}

所有这些解决方案都将传播原始 CompletableFuture.

的异常(如果有)

感谢 ,您也可以只使用 thenAcceptConsumer 什么都不做:

public CompletableFuture<Void> packetEncrypted(ByteBuffer engineToSocketData) {
    return realChannel.write(engineToSocketData).thenAccept(c -> {}):
}

任何其他类型的行为都相同。 thenApply 允许您对 CompletableFuture.

的结果执行任何 Function

例如,我可以有一个未来,它意味着要用 String 完成,它意味着要转换为 Integer

public static void main(String[] args) throws Exception {
    CompletableFuture<String> futureLine = CompletableFuture.supplyAsync(() -> "1234");
    CompletableFuture<Integer> theNumber = futureLine.thenApply(Integer::parseInt);
    System.out.println(theNumber.get());
}

thenApply 接收完成的值并通过将其传递给 Integer#parseInt(String) 的调用来转换它。由于 parseInt 有一个 return 类型的 int,return 类型的 thenApply 被推断为 CompletableFuture<Integer>.