递归太深导致栈溢出
栈溢出
在进行函数调用时,会将函数局部变量等信息压入栈中,在递归调用时如果层数太深,那么线程栈空间被耗尽,没有足够的内存分配给新创建的栈帧,就会导致java.lang.StackOverflowError
解决方案:
- 把递归调用函数更改为while或者for循环实现
- 通过尾递归优化,Java编译器不支持尾递归优化,可以手动实现但是此种实现方式不如使用循环进行优化直观
- 改用堆内存,函数中定义很大的局部变量,这种情况下可以将局部变量更改尾静态变量
- 增大栈的大小值,JVM中使用xss参数指定
实际案例
通过上面的解决方案可以看出,栈溢出通常有两种解决方法,第一是增大栈内存,第二是将递归更改为循环的方式。
增大栈内存大小虽然最为方便,但是如果递归的层数太深,不可能无限制的增大栈内存大小,仍旧会有栈溢出的情况出现,那么我们只有优化代码结构,将递归调用更改为循环调用。
树形结构,如果要遍历整个树进行一些统计,那么使用递归的方式最为方便直观,如下代码使用递归统计node节点下所有子节点的id
private void addChildren(List<String> ids, TreeNode node, ChildrenQuery query) {
if (CollectionUtils.isEmpty(node.getChildren())) {
return;
}
for (TreeNode child : node.getChildren()) {
if (query.isCascaded()) {
// 此处递归调用
addChildren(ids, child, query);
}
ids.add(child.getId());
}
}
树十几万节点,如果使用递归的方式统计会导致java.lang.StackOverflowError,那么只能将递归更改为循环的方式,如下所示
private void addChildren(List<String> ids, TreeNode node, ChildrenQuery query) {
if (CollectionUtils.isEmpty(node.getChildren())) {
return;
}
Deque<TreeNode> stack = new ArrayDeque<>();
node.getChildren().forEach(stack::push);
while (!stack.isEmpty()) {
TreeNode currentNode = stack.pop();
if (CollectionUtils.isNotEmpty(currentNode.getChildren()) && query.isCascaded()) {
for (TreeNode child : currentNode.getChildren()) {
stack.push(child);
}
}
ids.add(currentNode.getId());
}
}
本文作者:~鲨鱼辣椒~
本文链接:https://www.cnblogs.com/wrxiang/p/17699470.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

浙公网安备 33010602011771号