Java 足够堆叠溢出吗?
爪哇 在使用一个引用和两个整数作为参数进行10000次递归void函数调用后,出现堆栈溢出错误,这正常吗 获得6gb ram内存,尝试通过IDE和命令行运行。我很确定代码是正确的,递归应该完成 它是关于一个用于平铺贴图编辑器的填充工具。它从某个瓷砖开始,然后向上、向下、向右和向左移动,如果重合的瓷砖类型相同,并且没有返回 尝试了不同的方法,下面是一个附加布尔表,指示是否访问了[x][y]磁贴,并在递归完成后替换标记的磁贴:Java 足够堆叠溢出吗?,java,Java,爪哇 在使用一个引用和两个整数作为参数进行10000次递归void函数调用后,出现堆栈溢出错误,这正常吗 获得6gb ram内存,尝试通过IDE和命令行运行。我很确定代码是正确的,递归应该完成 它是关于一个用于平铺贴图编辑器的填充工具。它从某个瓷砖开始,然后向上、向下、向右和向左移动,如果重合的瓷砖类型相同,并且没有返回 尝试了不同的方法,下面是一个附加布尔表,指示是否访问了[x][y]磁贴,并在递归完成后替换标记的磁贴: public void fillRec(Tile t, int colu
public void fillRec(Tile t, int column, int row) {
if (affected[column][row] || t.getName() != pattern)
return;
/*t.replaceMe(editor.currentTileButton.spawnTile(column, row,
editor.tileMap));*/
affected[column][row] = true;
if (column < editor.tileMap.tilesX - 1) {
fillRec(editor.tileMap.tiles[column + 1][row], column + 1, row);
}
if (column > 0) {
fillRec(editor.tileMap.tiles[column - 1][row], column - 1, row);
}
if (row < editor.tileMap.tilesY - 1) {
fillRec(editor.tileMap.tiles[column][row + 1], column, row + 1);
}
if (row > 0) {
fillRec(editor.tileMap.tiles[column][row - 1], column, row - 1);
}
}
public void fillRec(Tile t,int列,int行){
if(受影响的[列][行]| | t.getName()!=模式)
返回;
/*t、 replaceMe(editor.currentTileButton.spawnTile(列、行、,
编辑:tileMap)*/
受影响的[列][行]=true;
if(列0){
fillRec(editor.tileMap.tiles[column-1][row],column-1,row);
}
如果(行0){
fillRec(editor.tileMap.tiles[column][row-1],column,row-1);
}
}
这在~75x75映射下运行良好,函数替换平铺和在其体内执行其他繁重的操作也是如此。是的,每个方法调用都会使用一个堆栈帧。如果您想在Java中使用大规模递归,您需要使用蹦床,它可以将堆栈空间交换为堆空间。蹦床通常有两种状态
Trampoline<Integer> loop(int times,int sum){
if(times==0)
return Trampoline.done(sum);
else
return Trampoline.more(()->loop(times-1,sum+times));
}
请注意,该方法立即返回一个懒惰的Trampoline对象(即,它不执行求和),当调用结果时,Trampoline将以迭代而不是递归的方式通过简单求和算法运行
我写的一个库中有一个蹦床实现,名为“可以使用”。或者,如果您愿意,这里是如何实现您自己的(此实现利用了Mario Fusco的一项优秀技术,在Java8流中管理蹦床迭代)
公共界面蹦床{
默认蹦床反弹(){
归还这个;
}
T结果();
默认布尔完成(){
返回true;
}
公共静态蹦床完成(T结果){
返回()->结果;
}
公共静态蹦床更多(蹦床){
返回新蹦床(){
@凌驾
公共布尔完成(){
返回false;
}
@凌驾
公众蹦床弹跳{
返回蹦床。结果();
}
公营医疗服务结果({
返回蹦床(本);
}
蹦床{
返回流。迭代(蹦床,蹦床::弹跳)
.过滤器(蹦床::完成)
.findFirst()
.get()
.result();
}
};
}
}
是的,每个方法调用都会使用一个堆栈帧。如果您想在Java中使用大规模递归,您需要使用蹦床,它可以将堆栈空间交换为堆空间。蹦床通常有两种状态
Trampoline<Integer> loop(int times,int sum){
if(times==0)
return Trampoline.done(sum);
else
return Trampoline.more(()->loop(times-1,sum+times));
}
请注意,该方法立即返回一个懒惰的Trampoline对象(即,它不执行求和),当调用结果时,Trampoline将以迭代而不是递归的方式通过简单求和算法运行
我写的一个库中有一个蹦床实现,名为“可以使用”。或者,如果您愿意,这里是如何实现您自己的(此实现利用了Mario Fusco的一项优秀技术,在Java8流中管理蹦床迭代)
公共界面蹦床{
默认蹦床反弹(){
归还这个;
}
T结果();
默认布尔完成(){
返回true;
}
公共静态蹦床完成(T结果){
返回()->结果;
}
公共静态蹦床更多(蹦床){
返回新蹦床(){
@凌驾
公共布尔完成(){
返回false;
}
@凌驾
公众蹦床弹跳{
返回蹦床。结果();
}
公营医疗服务结果({
返回蹦床(本);
}
蹦床{
返回流。迭代(蹦床,蹦床::弹跳)
.过滤器(蹦床::完成)
.findFirst()
.get()
.result();
}
};
}
}
是的,每个方法调用都会使用一个堆栈帧。如果您想在Java中使用大规模递归,您需要使用蹦床,它可以将堆栈空间交换为堆空间。蹦床通常有两种状态
public interface Trampoline<T> {
default Trampoline<T> bounce(){
return this;
}
T result();
default boolean complete() {
return true;
}
public static <T> Trampoline<T> done(T result) {
return () -> result;
}
public static <T> Trampoline<T> more(Trampoline<Trampoline<T>> trampoline) {
return new Trampoline<T>() {
@Override
public boolean complete() {
return false;
}
@Override
public Trampoline<T> bounce() {
return trampoline.result();
}
public T result() {
return trampoline(this);
}
T trampoline(Trampoline<T> trampoline) {
return Stream.iterate(trampoline,Trampoline::bounce)
.filter(Trampoline::complete)
.findFirst()
.get()
.result();
}
};
}
}