Java 增加堆栈大小是否被认为是一种不好的做法?

Java 增加堆栈大小是否被认为是一种不好的做法?,java,stack-overflow,depth-first-search,Java,Stack Overflow,Depth First Search,我在Java程序中得到了StackOverflowException,因此我使用-Xss100m增加了堆栈大小。这是否意味着我的代码有问题?我需要解决以下任务: 你有n件衣服 对于每一件衣服x,y,你知道x和y的搭配是否合适 把所有的衣服都放在最大数量的衣柜里,但你必须确保当你从每个衣柜里拿出一件衣服时,它看起来会很好(所以每件衣服都必须看起来很好) 我将其实现为一个图,其中顶点是衣服,当两个顶点彼此看起来不合适时,两个顶点之间有一条边。所以基本上我需要把每个连接顶点的“组”放在一个衣柜里。为此

我在Java程序中得到了StackOverflowException,因此我使用
-Xss100m
增加了堆栈大小。这是否意味着我的代码有问题?我需要解决以下任务:

  • 你有n件衣服
  • 对于每一件衣服x,y,你知道x和y的搭配是否合适
  • 把所有的衣服都放在最大数量的衣柜里,但你必须确保当你从每个衣柜里拿出一件衣服时,它看起来会很好(所以每件衣服都必须看起来很好)
  • 我将其实现为一个图,其中顶点是衣服,当两个顶点彼此看起来不合适时,两个顶点之间有一条边。所以基本上我需要把每个连接顶点的“组”放在一个衣柜里。为此,我使用简单DFS:

    SimpleGraph类的一部分

        Map<Integer, List<Integer>> edges;
    
        /**
         * Recursive implementation of DFS algorithm adjusted to SimpleGraph class
         * 
         * @param vertice               id of vertice we start at
         * @param visited               array holding info if given vertice was visited or not
         * @param applyToEachVertice    function applied to each vertice we visit
         * @return                      did we marked ANY vertice as visited ( if we DFS starting at
         *                               visited vertice it returns false and true otherwise )
         */
        boolean deepFirstSearch( int vertice, boolean[] visited, Consumer<Integer> applyToEachVertice )
        {
            if(visited[vertice])
               return false;
            visited[vertice] = true;
            applyToEachVertice.accept(vertice);
    
            // checks if vertice has any neighbours
            if(!edges.containsKey(vertice))
                return true;
    
            for( int v : edges.get(vertice) )
                if(!visited[v]) 
                    deepFirstSearch(v, visited, applyToEachVertice);
            return true;
        }
    
    映射边缘;
    /**
    *调整为SimpleGraph类的DFS算法的递归实现
    * 
    *@param vertice我们开始的vertice id
    *@param已访问阵列,如果已访问或未访问给定的vertice,则保留信息
    *@param applyToEachVertice函数应用于我们访问的每个vertice
    *@return我们是否将任何vertice标记为已访问(如果我们从
    *已访问vertice返回false,否则返回true)
    */
    布尔deepFirstSearch(int vertice、访问的布尔[]、消费者应用程序EachVertice)
    {
    如果(访问[垂直])
    返回false;
    访问[垂直]=真实;
    applyToEachVertice.接受(vertice);
    //检查vertice是否有邻居
    如果(!edges.containsKey(垂直))
    返回true;
    for(int v:edges.get(vertice))
    如果(!已访问[v])
    deepFirstSearch(v、已访问、适用于每个社区);
    返回true;
    }
    
    主回路

        void resolve( SimpleGraph sg )
        {
            boolean[] visited = new boolean[sg.getVertNumber()];
            final int[] wardrobe = new int[sg.getVertNumber()];        
            for(int i = 0, warNr = 0; i < sg.getVertNumber(); i++)
            {
                final int cNr = warNr;
                if(sg.deepFirstSearch(i, visited, x -> wardrobe[x] = cNr))
                    warNr++;
            }
        }
    
    void解析(SimpleGraph sg)
    {
    boolean[]已访问=新的boolean[sg.getVertNumber()];
    最终整数[]衣柜=新整数[sg.getVertNumber()];
    for(inti=0,warner=0;i衣柜[x]=cNr))
    华纳++;
    }
    }
    
    编辑:以迭代方式实际实现DFS解决了问题。这意味着我可以在不改变堆栈大小的情况下运行我的应用程序

    boolean deepFirstSearchNotRecursive( int vertice, boolean[] visited, Consumer<Integer> applyToEachVertice )
    {
        if(visited[vertice])
            return false;
    
        Deque<Integer> stack = new ArrayDeque<>();  
        stack.push(vertice);
    
        while(!stack.isEmpty())
        {
            Integer next = stack.pop();
            visited[next] = true;
            applyToEachVertice.accept(next);
            if(!edges.containsKey(next))
                continue;
            for(Integer i : edges.get(next))
                if(!visited[i])
                    stack.push(i);
        }
    
        return true;
    }
    
    boolean deepFirstSearchNotRecursive(int-vertice,boolean[]已访问,消费者应用程序每个权限)
    {
    如果(访问[垂直])
    返回false;
    Deque stack=new ArrayDeque();
    栈.推(垂直);
    而(!stack.isEmpty())
    {
    整数next=stack.pop();
    访问[下一步]=真;
    applyToEachVertice.accept(下一步);
    如果(!edges.containsKey(下一个))
    继续;
    for(整数i:edges.get(下一个))
    如果(!访问[i])
    堆栈推送(i);
    }
    返回true;
    }
    
    我假定您的问题不是由无限递归引起的,因为您可以从
    StackOverflowException
    stacktrace中发现问题,扩展堆栈大小对您没有帮助

    虽然有充分的理由增加堆栈跟踪大小,但我敢说,调用链的深度与传递给应用程序的输入的大小成正比。在这种情况下,您永远无法将其配置得足够大(如果您不限制输入的大小,这对于图形来说可能是一件棘手的事情)。切换到递归深度独立于输入数据的算法是一种方法


    当然,如果您有预定义的数据集,或者编写了一个永远不会重复使用的一次性脚本,那么捷径比重新实现算法的核心更可取。

    如果您知道可以这样做并且可以安全地使用它,则可以增加堆栈大小。否则,我会尝试看看一个不同的算法是否有助于从一开始就避免SO。如果让我猜的话,我会说你可能陷入了一个无限循环,所以你的内存用完了。如果增加堆栈大小可以解决问题,那么很可能不是无限循环。我错了吗?顺便说一句,将DFS实现为非递归方法现在解决了这个问题:)我从来没有出现过无法通过修复代码来修复的堆栈溢出。因此,看看我的代码,你有没有看到任何简单的方法来修复此问题(除了已经修复的方法)?