Java 8 仅当达到某个条件时才链接多个CompletionStage
我有几个Java 8 仅当达到某个条件时才链接多个CompletionStage,java-8,completable-future,Java 8,Completable Future,我有几个CompletionStage方法要链接。问题是,第一个的结果将决定是否应该执行下一个。现在实现这一点的唯一方法似乎是将“特殊”参数传递给下一个CompletionStage,这样它就不会执行完整的代码。例如: public enum SomeResult { RESULT_1, RESULT_2, RESULT_3 } public CompletionStage<SomeResult> someMethod(SomeArgument someAr
CompletionStage
方法要链接。问题是,第一个的结果将决定是否应该执行下一个。现在实现这一点的唯一方法似乎是将“特殊”参数传递给下一个CompletionStage
,这样它就不会执行完整的代码。例如:
public enum SomeResult {
RESULT_1,
RESULT_2,
RESULT_3
}
public CompletionStage<SomeResult> someMethod(SomeArgument someArgument) {
return CompletableFuture.supplyAsync(() -> {
// loooooong operation
if (someCondition)
return validValue;
else
return null;
}).thenCompose(result -> {
if (result != null)
return someMethodThatReturnsACompletionStage(result);
else
return CompletableFuture.completedFuture(null);
}).thenApply(result -> {
if (result == null)
return ChainingResult.RESULT_1;
else if (result.someCondition())
return ChainingResult.RESULT_2;
else
return ChainingResult.RESULT_3;
});
}
公共枚举结果{
结果1,
结果2,
结果3
}
公共CompletionStage someMethod(SomeArgument SomeArgument){
返回CompletableFuture.SupplySync(()->{
//Looooong手术
如果(某些条件)
返回有效值;
其他的
返回null;
}).然后撰写(结果->{
如果(结果!=null)
返回返回CompletionStage(结果)的方法;
其他的
返回CompletableFuture.completedFuture(空);
})。然后应用(结果->{
如果(结果==null)
返回ChainingResult.RESULT_1;
else if(result.someCondition())
返回chainResult.RESULT_2;
其他的
返回chainResult.RESULT_3;
});
}
由于整个代码依赖于第一个
someCondition
(如果它是false
,则结果将是result\u 1
,如果不是,则应执行整个代码),因此这种构造在我看来有点难看。有没有办法决定是否应该执行第二个(然后组合(…)
)和第三个(然后应用(…)
)方法
public CompletionStage<SomeResult> someMethod(SomeArgument someArgument) {
CompletableFuture<SomeResult> shortCut = new CompletableFuture<>();
CompletableFuture<ResultOfFirstOp> withChain = new CompletableFuture<>();
CompletableFuture.runAsync(() -> {
// loooooong operation
if (someCondition)
withChain.complete(validValue);
else
shortCut.complete(SomeResult.RESULT_1);
});
return withChain
.thenCompose(result -> someMethodThatReturnsACompletionStage(result))
.thenApply(result ->
result.someCondition()? SomeResult.RESULT_2: SomeResult.RESULT_3)
.applyToEither(shortCut, Function.identity());
}
public CompletionStage<SomeResult> someMethod(SomeArgument someArgument) {
CompletableFuture<Object> shortCut = new CompletableFuture<>();
CompletableFuture<ResultOfFirstOp> withChain = new CompletableFuture<>();
CompletableFuture.runAsync(() -> {
// loooooong operation
if (someCondition)
withChain.complete(validValue);
else
shortCut.complete(null);
});
return withChain
.thenCompose(result -> someMethodThatReturnsACompletionStage(result))
.thenApply(result ->
result.someCondition()? SomeResult.RESULT_2: SomeResult.RESULT_3)
.applyToEither(shortCut.thenApply(x -> SomeResult.RESULT_1), Function.identity());
}
如果您的第三步不是示例性的,但看起来与问题中所示完全相同,则可以将其与代码路径连接步骤合并:
public CompletionStage<SomeResult> someMethod(SomeArgument someArgument) {
CompletableFuture<ResultOfSecondOp> shortCut = new CompletableFuture<>();
CompletableFuture<ResultOfFirstOp> withChain = new CompletableFuture<>();
CompletableFuture.runAsync(() -> {
// loooooong operation
if (someCondition)
withChain.complete(validValue);
else
shortCut.complete(null);
});
return withChain
.thenCompose(result -> someMethodThatReturnsACompletionStage(result))
.applyToEither(shortCut, result -> result==null? SomeResult.RESULT_1:
result.someCondition()? SomeResult.RESULT_2: SomeResult.RESULT_3);
}
public CompletionStage someMethod(SomeArgument SomeArgument){
CompletableFuture快捷方式=新建CompletableFuture();
CompletableFuture with chain=新的CompletableFuture();
CompletableFuture.runAsync(()->{
//Looooong手术
如果(某些条件)
withChain.complete(有效值);
其他的
快捷方式。完成(空);
});
连锁退货
。然后编写(结果->返回完成阶段(结果)的某些方法)
.applytoother(快捷方式,result->result==null?SomeResult.result\u 1:
result.someCondition()?SomeResult.result_2:SomeResult.result_3);
}
然后我们只跳过第二步,即返回CompletionStage调用的
SomeMethod,但它仍然可以代表一长串中间步骤,所有这些步骤都跳过了,而不需要通过nullcheck手动跳过。为了完整性,我添加了一个新的答案
尽管@Holger提出的解决方案非常有效,但对我来说有点奇怪。我一直在使用的解决方案包括在不同的方法调用中分离不同的流,并使用然后组合:
public enum SomeResult {
RESULT_1,
RESULT_2,
RESULT_3
}
public CompletionStage<SomeResult> someMethod(SomeArgument someArgument) {
return CompletableFuture.supplyAsync(() -> {
// loooooong operation
if (someCondition)
return operateWithValidValue(value);
else
return CompletableFuture.completedValue(ChainingResult.RESULT_1);
})
.thenCompose(future -> future);
public CompletionStage<SomeResult> operateWithValidValue(... value) {
// more loooong operations...
if (someCondition)
return CompletableFuture.completedValue(SomeResult.RESULT_2);
else
return doFinalOperation(someOtherValue);
}
public CompletionStage<SomeResult> doFinalOperation(... value) {
// more loooong operations...
if (someCondition)
return CompletableFuture.completedValue(SomeResult.RESULT_2);
else
return CompletableFuture.completedValue(SomeResult.RESULT_3);
}
公共枚举结果{
结果1,
结果2,
结果3
}
公共CompletionStage someMethod(SomeArgument SomeArgument){
返回CompletableFuture.SupplySync(()->{
//Looooong手术
如果(某些条件)
返回操作的有效值(value);
其他的
返回CompletableFuture.completedValue(chainResult.RESULT_1);
})
.然后编写(未来->未来);
公共CompletionStage操作的有效值(…值){
//更多龙龙行动。。。
如果(某些条件)
返回CompletableFuture.completedValue(SomeResult.RESULT_2);
其他的
返回doFinalOperation(someOtherValue);
}
公共CompletionStage doFinalOperation(…值){
//更多龙龙行动。。。
如果(某些条件)
返回CompletableFuture.completedValue(SomeResult.RESULT_2);
其他的
返回CompletableFuture.completedValue(SomeResult.RESULT_3);
}
注意:为了得到更完整的答案,我更改了问题的算法
所有的长操作都可能被包装在另一个CompletableFuture中。如果您只需要检查空值,则可以使用Optional
解决。例如,您应该执行以下操作:
public Bar execute(String id) {
return this.getFooById(id)
.thenCompose(this::checkFooPresent)
.thenCompose(this::doSomethingElse)
.thenCompose(this::doSomethingElseMore)
.thenApply(rankRes -> new Bar(foo));
}
private Optional<Foo> getFooById(String id) {
// some better logic to retrieve foo
return Optional.ofNullable(foo);
}
private CompletableFuture<Foo> checkFooPresent(Optional<Foo> optRanking) {
CompletableFuture<Foo> future = new CompletableFuture();
optRanking.map(future::complete).orElseGet(() -> future.completeExceptionally(new Exception("Foo not present")));
return future;
}
公共条执行(字符串id){
返回此.getFooById(id)
.thenCompose(此::checkFooPresent)
.然后撰写(此::doSomethingElse)
.然后合成(此::doSomethingelsMore)
。然后应用(rankRes->newbar(foo));
}
私有可选getFooById(字符串id){
//检索foo的一些更好的逻辑
返回可选。未满(foo);
}
私有CompletableFuture checkFooPresent(可选操作传输){
CompletableFuture=新的CompletableFuture();
optRanking.map(future::complete).OrelGet(()->future.completeException(新异常(“Foo不存在”));
回归未来;
}
checkFooPresent()
接收一个可选的,如果其值为null
则异常完成CompletableFuture
显然,您需要管理该异常,但是如果您以前设置过异常处理程序
或类似的程序,那么它应该是免费的。它可以工作,谢谢!遵循相同的模式(创建几个CompletableFuture
并使用应用程序(…)
)那么就有可能将其扩展到多个路径,对吗?是的,您可以将其扩展到多个路径,但必须注意保持生成的代码的可维护性。也许这有助于将分支的逻辑封装到一个实用方法中,您可以多次使用。