java 如何避免递归函数的 StackOverflowError
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10073471/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to avoid StackOverflowError for a recursive function
提问by Henrik Karlsson
I'm writing a function that will call itself up to about 5000 times. Ofcourse, I get a StackOverflowError
. Is there any way that I can rewrite this code in a fairly simple way?:
我正在编写一个最多可调用 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
}
By the way, what is the limitation of how deep we may call the functions?
顺便说一下,我们调用函数的深度有什么限制?
回答by Richante
Use an explicit stack of objects and a loop, rather than the call stack and recursion:
使用明确的对象堆栈和循环,而不是调用堆栈和递归:
void checkBlocks(Block b, int amm) {
Stack<Block> blocks = new Stack<Block>();
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);
}
}
回答by Anish Dasappan
default stack size in java is 512kb. if you exceed that program will terminate throwing StackOverflowException
java 中的默认堆栈大小为 512kb。如果超过该程序将终止抛出 StackOverflowException
you can increase the stack size by passing a JVM argument : -Xss1024k
您可以通过传递 JVM 参数来增加堆栈大小:-Xss1024k
now stack size is 1024kb. you may give higher value based on your environment
现在堆栈大小是 1024kb。您可能会根据您的环境提供更高的价值
I don't think we can programmatically change this
我认为我们不能以编程方式改变这一点
回答by zip
In most cases recursion is used in a wrong way. You shouldn't get a stack over flow exception. Your method has no return type/value. How do you ensure your initial Block b is valid?
在大多数情况下,递归的使用方式是错误的。你不应该得到堆栈溢出异常。您的方法没有返回类型/值。你如何确保你的初始区块 b 是有效的?
If you are using recursion, answer yourself the following question:
如果您使用递归,请回答自己以下问题:
- what is my recursion anchor (when do i stop with recursion)
- what is my recursion step (how do I reduce my number of calculations)
- 什么是我的递归锚点(我什么时候停止递归)
- 我的递归步骤是什么(如何减少计算次数)
Example:
例子:
- n! => n*n-1!
- 啊!=> n*n-1!
my recursion anchor is n == 2 (result is 2), so I can calculate all results beginnging from this anchor.
我的递归锚点是 n == 2(结果是 2),所以我可以计算从这个锚点开始的所有结果。
my recursion step is n-1 (so each step I get closer to the solution (and in this fact to my recursion anchor))
我的递归步骤是 n-1(所以每一步我都更接近解决方案(实际上是我的递归锚点))
回答by Sandro
You can increase the stack size by using -Xss4m.
您可以使用 -Xss4m 增加堆栈大小。
回答by stefan bachert
You may put your "Block"s into a queue/stack and iterate as long as Blocks are available.
只要块可用,您就可以将“块”放入队列/堆栈中并进行迭代。
回答by mishadoff
It's obvious that you get StackOverflow with such branching factor of your recursion. In other languages it can be achieved by Tail Call Optimization. But I suppose your problem needs another way to solve.
很明显,您使用递归的这种分支因子获得了 StackOverflow。在其他语言中,它可以通过尾调用优化来实现。但我想你的问题需要另一种方法来解决。
Ideally, you perform some check on Block. Maybe you can obtain list of all blocks and check each of them iteratively?
理想情况下,您对 Block 执行一些检查。也许您可以获得所有块的列表并迭代检查它们中的每一个?