为什么编译器给我这不能从 CompletableFuture<Object> 转换为 CompletableFuture<String>
Why compiler in given me this cannot convert from CompletableFuture<Object> to CompletableFuture<String>
我正在尝试使用 CompletableFuture 链接一些文件处理程序,这应该是 return a 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()
returns CompletableFuture<Void>
,所以我在其 thenApply()
...
中生成一个字符串
但为什么编译器假设我在这里生成 CompletableFuture<Object>
?
请问我在这里遗漏了什么?
顺便说一句,像这样链接方法是更好的方法吗?
你的主要条款是
CompletableFuture<String> allGen = loadFile1().thenApply(params1 -> {
…
});
所以指定函数应该return一个String
。但是你的代码试图 return 一个 CompletableFuture<String>
,因为 Stream.of(gen1, gen2) .map(CompletableFuture::join) .collect(joining(","))
产生一个 String
而你在 return CompletableFuture .allOf(gen1, gen2) .thenApply(r -> …);
中使用这个表达式
对于泛型代码中此类类型不匹配的情况,编译器错误消息通常毫无帮助。
最简单的修复(变化最小)是使用 thenCompose
而不是 thenAppy
,允许函数 return a 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
。后者的效率会稍微高一些,但由于它不太可能主导整体性能,所以这是一个品味问题。
我正在尝试使用 CompletableFuture 链接一些文件处理程序,这应该是 return a 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()
returns CompletableFuture<Void>
,所以我在其 thenApply()
...
但为什么编译器假设我在这里生成 CompletableFuture<Object>
?
请问我在这里遗漏了什么?
顺便说一句,像这样链接方法是更好的方法吗?
你的主要条款是
CompletableFuture<String> allGen = loadFile1().thenApply(params1 -> {
…
});
所以指定函数应该return一个String
。但是你的代码试图 return 一个 CompletableFuture<String>
,因为 Stream.of(gen1, gen2) .map(CompletableFuture::join) .collect(joining(","))
产生一个 String
而你在 return CompletableFuture .allOf(gen1, gen2) .thenApply(r -> …);
对于泛型代码中此类类型不匹配的情况,编译器错误消息通常毫无帮助。
最简单的修复(变化最小)是使用 thenCompose
而不是 thenAppy
,允许函数 return a 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
。后者的效率会稍微高一些,但由于它不太可能主导整体性能,所以这是一个品味问题。