如何避免递归函数的StackOverflowError

我正在编写一个函数,可以调用自己大约5000次。 当然,我得到一个StackOverflowError 。 有什么方法可以用相当简单的方式重写这段代码吗?:

 void checkBlocks(Block b, int amm) { //Stuff that might issue a return call Block blockDown = (Block) b.getRelative(BlockFace.DOWN); if (condition) checkBlocks(blockDown, amm); Block blockUp = (Block) b.getRelative(BlockFace.UP); if (condition) checkBlocks(blockUp, amm); //Same code 4 more times for each side } 

顺便说一下,我们可以称之为function的深度有多大?

使用显式堆栈对象和循环,而不是调用堆栈和递归:

 void checkBlocks(Block b, int amm) { Stack blocks = new Stack(); blocks.push(b); while (!blocks.isEmpty()) { b = blocks.pop(); Block blockDown = (Block) b.getRelative(BlockFace.DOWN); if (condition) blocks.push(block); Block blockUp = (Block) b.getRelative(BlockFace.UP); if (condition) blocks.push(block); } } 

java中的默认堆栈大小为512kb。 如果超过该程序将终止抛出StackOverflowException

您可以通过传递JVM参数来增加堆栈大小:-Xss1024k

现在堆栈大小是1024kb。 您可以根据您的环境提供更高的价值

我认为我们不能以编程方式改变这一点

您可以使用-Xss4m增加堆栈大小。

您可以将“块”放入队列/堆栈中,只要块可用就进行迭代。

很明显,你的StackOverflow具有递归的分支因子。 在其他语言中,它可以通过Tail Call Optimization实现。 但我想你的问题需要另一种方法来解决。

理想情况下,您对Block执行一些检查。 也许你可以获得所有块的列表并迭代地检查它们中的每一个?

在大多数情况下,递归以错误的方式使用。 您不应该获得堆栈溢出exception。 您的方法没有返回类型/值。 您如何确保您的初始Block b有效?

如果您正在使用递归,请回答以下问题:

  • 什么是我的递归锚(什么时候我停止递归)
  • 什么是我的递归步骤(如何减少我的计算次数)

例:

  • N! => n * n-1!

我的递归锚点是n == 2(结果是2),所以我可以计算从这个锚点开始的所有结果。

我的递归步骤是n-1(所以每一步我都接近解决方案(在这个事实中我的递归锚))