Как избежать 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
}
кстати, каково ограничение того, насколько глубоко мы можем называть функции?
6 ответов
используйте явный стек объектов и цикл, а не стек вызовов и рекурсию:
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);
}
}
размер стека по умолчанию в java - 512kb. если вы превысите, что программа прекратит бросать StackOverflowException
вы можете увеличить размер стека, передав аргумент JVM : - Xss1024k
теперь размер стека 1024kb. вы можете дать более высокое значение на основе вашей среды
Я не думаю, что мы можем программно изменить этот
очевидно, что вы получаете StackOverflow с таким коэффициентом ветвления вашей рекурсии. На других языках это может быть достигнуто оптимизацией хвостового вызова. Но я полагаю, что ваша проблема нуждается в другом способе решения.
В идеале, вы выполняете некоторую проверку на блоке. Может быть, вы можете получить список всех блоков и проверить каждый из них последовательно?
в большинстве случаев рекурсия используется неправильно. Вы не должны получать stack over flow exception. Ваш метод не имеет возвращаемого типа / значения. Как вы гарантируете, что ваш начальный блок b действителен?
Если вы используете рекурсию, ответьте себе на следующий вопрос:
- каков мой якорь рекурсии (когда я останавливаюсь на рекурсии)
- каков мой шаг рекурсии (как уменьшить количество расчеты)
пример:
- n! => n*n-1!
мой якорь рекурсии n == 2 (результат 2), поэтому я могу вычислить все результаты, начинающиеся с этого якоря.
Мой шаг рекурсии-n-1 (поэтому с каждым шагом я приближаюсь к решению (и в этом факте к моему якорю рекурсии))