如何防止无限递归循环

时间:2019-11-27 13:43:46

标签: java recursion infinite-recursion

我似乎无法解决我的递归问题。因此,我有一个Version对象,该对象保存了对它依赖的其他版本对象的引用列表。

版本

{
  "id": "id1",
  "version": "1",
  "dependencies": [
    {
      "id": "id2"
    },
    {
      "id": "id3"
    }
  ]
}

当我检索此对象时,我还必须检索它的依赖关系以及依赖关系的依赖关系,直到最终结果看起来像这样

VersionDto

{
  "id": "id1",
  "version": "1",
  "dependencies": [
    {
      "id": "id2",
      "version": "2",
      "dependencies": [
        {
          "id": "id4",
          "version": "4",
          "dependencies": []
        }
      ]
    },
    {
      "id": "id3",
      "version": "3",
      "dependencies": []
    }
  ]
}

这是我的递归函数,用于检索版本

public VersionDto getVersion(String id)
{
    //Retrieves from database
    Version version = versionDAO.getVersion(id);

    //Convert to Dto (basic fields)
    VersionDto versionDto = new VersionDto(version);

    //Recursivly retrieve dependencies 
    for (Map<String, String> dep : version.getDependencies()) {
        VersionDto dto = new VersionDto();

        //Recursive call
        dto = getVersion(dep.get("id"));
        versionDto.getDependencies().add(dto);
    }

    return versionDto;
}

但是,在版本可能是其中一个嵌套依赖项的依赖项,例如v1-> v2-> v4-> v1导致无限重复的情况下,我遇到了可能的无限循环的问题。

有什么办法可以解决和防止这种无限循环的想法,因此,如果所有版本都准备就绪了,应该跳过它吗?

编辑:使用全局列表的解决方案

public VersionDto getVersion(String id)
{

    //Check global list contains version
    if (visited.contains(id)) {
        return null;
    }

    visited.add(docId);

    //Retrieves from database
    Version version = versionDAO.getVersion(id);

    //Convert to Dto (basic fields)
    VersionDto versionDto = new VersionDto(version);

    //Recursivly retrieve dependencies 
    for (Map<String, String> dep : version.getDependencies()) {
        VersionDto dto = new VersionDto();

        //Recursive call
        dto = getVersion(dep.get("id"));
        if(dep!= null) {
        versionDto.getDependencies().add(dto);
        }
    }

    return versionDto;
}

3 个答案:

答案 0 :(得分:1)

确保递归函数将结束的最好方法是设置一个或多个条件。您必须有一个,以确保它不会无限循环。

我建议创建一个数组或一个列表,在其中存储所有已经访问过的节点,因此在运行递归函数时,您可以知道自己已经访问过一个节点,并且可以移动到另一个节点。

答案 1 :(得分:1)

希望这会有所帮助。

如果v1的依赖关系始终相同,则它将起作用。

        dto = getVersion(dep.get("id"));
        //check if the versionDto contains the dependecy already then break the loop here
        versionDto.getDependencies().add(dto);```

答案 2 :(得分:1)

使用Jackson库可以非常有效地解决无限递归循环问题。 Jackson库会派上用场,特别是如果您使用Hibernate / JPA进行持久化。即,@JsonManagedReference和@JsonBackReference批注将适用于您的情况。

您尚未显示您的JPA实体代码,因此我无法告诉您应该在何处放置这些批注。但是,有关如何使用它们的一个很好的示例可以在

上找到。

http://springquay.blogspot.com/2016/01/new-approach-to-solve-json-recursive.html

希望您发现它有用!