【问题标题】:How to resolve OutOfMemoryError: Java heap space when traversing to find all possible paths with huge graph?如何解决 OutOfMemoryError: Java heap space when traversing to find all possible paths with large graph?
【发布时间】:2021-01-30 14:12:23
【问题描述】:

我正在实现一个图遍历来查找所有可能的路径,它适用于一个小样本图。但是当我把它带到一个更大的图(有 1000 个顶点)时,程序崩溃了 OutOfMemoryError: Java heap space。错误发生在第 13 行的str += src + " -> ";

有没有更好的解决方案?谢谢!

这是遍历的代码

private void displayPathRec( String src, String dest, String str )
{
    DSALinkedList ll = null;
    DSAGraphVertex v = null;

    ll = getAdjacent( src );
    Iterator iter = ll.iterator();

    // Base Case: found endLabel
    if( !src.equals( dest ) )
    {
        str += src + " -> ";
        while( iter.hasNext() )
        {
            v = (DSAGraphVertex) iter.next();
            displayPathRec( v.getLabel(), dest, str );
        }
    }
    else
        System.out.println(str + dest);
}

我的图表示例

    graph.addVertex("A", 25);
    graph.addVertex("B", 60);
    graph.addVertex("C", 45);
    graph.addVertex("D", 75);
    graph.addVertex("E", 95);
    graph.addVertex("F", 85);
    graph.addVertex("T", 115);
    graph.addVertex("G", 105);

    graph.addEdge("A", "B", "AB", "");
    graph.addEdge("A", "D", "AD", "");
    graph.addEdge("A", "C", "AC", "");
    graph.addEdge("A", "E", "AE", "");
    graph.addEdge("B", "E", "BE", "");
    graph.addEdge("E", "F", "EF", "");
    graph.addEdge("E", "G", "EG", "");
    graph.addEdge("D", "C", "DC", "");
    graph.addEdge("D", "F", "DF", "");
    graph.addEdge("F", "T", "FT", "");
    graph.addEdge("F", "G", "FG", "");
    graph.addEdge("T", "G", "TG", "");
    graph.addEdge("C", "F", "CF", ""); 

    DSALinkedList adjList = null;
    DSAGraphVertex v = null;
    String src = "A", dest = "G";

    graph.displayPath( src, dest );

输出

A -> B -> E -> F -> T -> G
A -> B -> E -> F -> G
A -> B -> E -> G
A -> D -> C -> F -> T -> G
A -> D -> C -> F -> G
A -> D -> F -> T -> G
A -> D -> F -> G
A -> C -> F -> T -> G
A -> C -> F -> G
A -> E -> F -> T -> G
A -> E -> F -> G
A -> E -> G

这是一个工作示例,但是当我尝试将它与更大的图表一起使用时,程序崩溃了。

这是我的getAdjacent,给定顶点的标签,它将返回顶点的邻接列表。

public DSALinkedList getAdjacent( String inLabel )
{
    DSAGraphVertex v = null;

    if( !hasVertex(inLabel) )                       // If inLabel does not exists means vertex is not exists
        throw new IllegalArgumentException("Label does not exist");

    else
    {
        boolean found = false;
        
        Iterator iter = vertices.iterator();        // Iterate through vertices becase we want to get
                                                    // link list of vertex and link list is fields of vertex
        // ASSERTION: Iterate over vertices (to search for the desired vertex)
        while( iter.hasNext() && !found )
        {
            v = (DSAGraphVertex)iter.next();
            found = v.getLabel().equals(inLabel);
        }
    }
    return v.getAdjacent();  // Return vertex list
}

【问题讨论】:

  • 这些类在哪里:DSALinkedList、DSAGraphVertex? getAdjacent(..) 方法有什么作用?你能发布一个功能完整的例子吗?
  • DSALinkedList 等价于 java 中的 。 DSAGraphVertex 表示每个顶点的顶点。请参考我更新的问题,了解 getAdjacent 方法的作用

标签: java recursion data-structures out-of-memory graph-traversal


【解决方案1】:

这不是递归逻辑的问题,否则你会得到一个 stackoverflow 异常而不是完整的堆。听起来您正在循环遍历图形的相同节点。

在没有看到数据集和整个逻辑的情况下,很难理解问题,但尝试实施检查以避免遍历过程中的循环(如果节点被访问,则停止),看看这是否解决了问题。

【讨论】:

    【解决方案2】:

    我在收集大量 html 作为字符串时也遇到了这种问题。我认为您应该使用 StringBuilder 类而不是 String,因为每次添加 String 时都会创建新对象。

    如果您的代码在生产/测试环境中中断(不在本地),那么您应该检查服务器的内存和 CPU 分配以及使用哪种垃圾收集器。 (我用的是 G1GC)。

    【讨论】:

      【解决方案3】:

      你知道一个有 1000 个边界的顶点有多少种可能性吗?尝试获得该问题的答案并重新考虑您的应用程序。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-12-25
        • 2014-06-15
        • 1970-01-01
        • 1970-01-01
        • 2019-12-30
        相关资源
        最近更新 更多