首页 > 解决方案 > 如何打破递归函数的多个实例调用?

问题描述

我正在创建一个递归函数,它将在图中找到两个节点之间的路径。只有在节点不重复时才会找到路径。如果一个节点连接到其他两个节点,则将创建递归函数的两个实例。如果两者都有正确的路径,则将设置最后找到的路径而不是第一个路径(行 this.nodePath = clonedNodePath;)。找到路径后,如何中断所有递归调用,而不仅仅是中断当前的递归调用实例?(我不想抛出异常)

private void process(String currentNodeId, List<String> currentNodePath) {
        FlowNode currentFlowNode = modelInstance.getModelElementById(currentNodeId);

        List<String> clonedNodePath = new ArrayList<>(currentNodePath);

        if (currentFlowNode == null || clonedNodePath.contains(currentNodeId)) return;

        clonedNodePath.add(currentNodeId);

        if (currentNodeId.equals(finishNodeId)) {
            this.nodePath = clonedNodePath;
            return;
        }

        currentFlowNode.getOutgoing()
                .stream()
                .forEach(sequenceFlow -> process(sequenceFlow.getTarget().getId(), clonedNodePath));

}

标签: javarecursiongraph

解决方案


主要问题在于对传出egdes的迭代。

您选择使用 Java8 流来执行此操作,这不允许您提前中止(挑剔:您可以解决该“限制”,但这很笨拙)。

将其更改为经典for循环,您的问题大部分都会消失。让您的process()方法返回一个布尔成功指示,并在循环内,如果它给出 true,则在此process()递归调用中返回 true。

或者更优雅:让process()方法返回一个Optional<List<String>>,如果失败则为空,如果成功则填充路径。然后你也摆脱了通过this.nodePath. 并且 process() 方法最好命名为findPath().

PS 我知道使用流很流行,但在某些情况下它们根本不是合适的工具。


推荐阅读