我最初编写这段代码是因为这是我的看法,但是我想研究如何删除递归。

这个想法是我有一个要渲染的指令列表。渲染器仅凭一条指令就给了我一个可以完成的未来。结果有时可能无效,因此我想在下一条指令上调用渲染器。我想返回呈现有效结果的第一条指令。

我想请一个学习的人看一下,并在可能的情况下给我一些想法。

/**
 * I want a a completable future for a list of instructions, returning
 * me the first valid result for the instruction input.
 */
private CompletableFuture<Result> getFutureResult(final List<Instruction> instructions) {
    final CompletableFuture<Result> futureResult = new CompletableFuture<>();
    renderAux(futureResult, instructions.iterator());
    return futureResult;
}

/**
 * This is actually an external method that will return a completable
 * future for only one instruction. I cannot modify this API.
 */
private CompletableFuture<Result> render(final Instruction instruction) {
    /.../
}

/**
 * This method is called recursively for the current instruction in the
 * the iterator, if the result if not valid, we call on the next instruction.
 */
private void renderAux(
        final CompletableFuture<Result> futureResult,
        final Iterator<Instruction> instructionIterator) {

    final Instruction instruction = instructionIterator.next();
    final boolean isLast = !instructionIterator.hasNext();
    render(instruction).whenComplete((result, e) -> {
        if (result.isValid() || isLast) {
            // Complete the future on the first valid result, or
            // if this is the last instruction.
            futureResult.complete(result);
        } else {
            // Recursive call for the next instruction.
            renderAux(futureResult, instructionIterator);
        }
    });
}

最佳答案

您可以直接使用CompletableFuture.handle()方法将期货链接在一起:

private CompletableFuture<Result> getFutureResult(final List<Instruction> instructions) {
    CompletableFuture<Result> futureResult = null;

    for (Instruction instruction : instructions) {
        if (futureResult == null) {
            futureResult = render(instruction);
        } else {
            futureResult = futureResult.handle((result, e) -> {
                if (result.isValid())
                    return result;
                else
                    return render(instruction).join();
            });
        }
    }

    return futureResult;
}


这会为您列表中的每条指令创造一个新的未来,但执行的指令数量仍然没有必要。

07-27 17:12