gpt4 book ai didi

generics - 为什么编译器给我这不能从 CompletableFuture 转换为 CompletableFuture
转载 作者:行者123 更新时间:2023-12-04 14:04:23 33 4
gpt4 key购买 nike

我正在尝试使用 CompletableFuture 链接一些文件处理程序,它应该返回 CompletableFuture<String> :

CompletableFuture<String> allGen = loadFile1().thenApply(params1 -> {

CompletableFuture<String> gen1 = loadFile2().thenApply(params2 -> {
return generateResultFile1(params1, params2);
});

CompletableFuture<String> gen2 = loadFile3().thenApply(params3 -> {
return generateResultFile2(params1, params3);
});

return CompletableFuture
.allOf(gen1, gen2)
.thenApply(r -> Stream.of(gen1, gen2).map(CompletableFuture::join).collect(joining(",")));
});

我知道CompletableFuture.allOf()返回 CompletableFuture<Void> ,所以我在其 thenApply() 中生成了一个字符串...

但为什么编译器假设我正在生成一个 CompletableFuture<Object>在这里?

请问我在这里遗漏了什么?

顺便说一句,像这样链接方法是更好的方法吗?

最佳答案

你的主要条款是

CompletableFuture<String> allGen = loadFile1().thenApply(params1 -> {

});

所以指定函数应该返回 String .但是您的代码试图返回 CompletableFuture<String> , 作为 Stream.of(gen1, gen2) .map(CompletableFuture::join) .collect(joining(","))产生 String你在 return CompletableFuture .allOf(gen1, gen2) .thenApply(r -> …); 中使用了这个表达式

在泛型代码中出现此类类型不匹配的情况下,编译器错误消息通常毫无帮助。

最简单的修复(变化最小)是使用 thenCompose而不是 thenAppy , 允许函数返回 CompletableFuture .

CompletableFuture<String> allGen = loadFile1().thenCompose(params1 -> {

CompletableFuture<String> gen1 = loadFile2().thenApply(params2 -> {
return generateResultFile1(params1, params2);
});

CompletableFuture<String> gen2 = loadFile3().thenApply(params3 -> {
return generateResultFile2(params1, params3);
});

return CompletableFuture.allOf(gen1, gen2)
.thenApply(r -> Stream.of(gen1, gen2)
.map(CompletableFuture::join).collect(joining(",")));
});

但是,有机会使用简化的语法

CompletableFuture<String> allGen = loadFile1().thenCompose(params1 -> {
CompletableFuture<String> gen1 = loadFile2()
.thenApply(params2 -> generateResultFile1(params1, params2));

CompletableFuture<String> gen2 = loadFile3()
.thenApply(params3 -> generateResultFile2(params1, params3));

return CompletableFuture.allOf(gen1, gen2)
.thenApply(r -> Stream.of(gen1, gen2)
.map(CompletableFuture::join).collect(joining(",")));
});

如果代码总是恰好组合两个结果,您可以使用更简单的方法:

CompletableFuture<String> allGen = loadFile1().thenCompose(params1 ->
loadFile2().thenApply(params2 -> generateResultFile1(params1, params2))
.thenCombine(
loadFile3().thenApply(params3 -> generateResultFile2(params1, params3)),
(s1, s2) -> String.join(",", s1, s2))
);

尽管嵌套不同,loadFile2().thenApply(…)loadFile3().thenApply(…)仍然是两个独立的操作,只有最后的(s1, s2) -> String.join(",", s1, s2)取决于两者。

如果你想让这个更明显,保留局部变量

CompletableFuture<String> allGen = loadFile1().thenCompose(params1 -> {
CompletableFuture<String> gen1
= loadFile2().thenApply(params2 -> generateResultFile1(params1, params2));
CompletableFuture<String> gen2
= loadFile3().thenApply(params3 -> generateResultFile2(params1, params3));
return gen1.thenCombine(gen2, (s1, s2) -> s1 + "," + s2);
});

如上例所示,您也可以替换 String.join(",", s1, s2)s1 + "," + s2这里。后者的效率会稍微高一些,但由于它不太可能主导整体性能,所以这更像是一个品味问题。

关于generics - 为什么编译器给我这不能从 CompletableFuture<Object> 转换为 CompletableFuture<String>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68996002/

33 4 0