Java 足够堆叠溢出吗?

Java 足够堆叠溢出吗?,java,Java,爪哇 在使用一个引用和两个整数作为参数进行10000次递归void函数调用后,出现堆栈溢出错误,这正常吗 获得6gb ram内存,尝试通过IDE和命令行运行。我很确定代码是正确的,递归应该完成 它是关于一个用于平铺贴图编辑器的填充工具。它从某个瓷砖开始,然后向上、向下、向右和向左移动,如果重合的瓷砖类型相同,并且没有返回 尝试了不同的方法,下面是一个附加布尔表,指示是否访问了[x][y]磁贴,并在递归完成后替换标记的磁贴: public void fillRec(Tile t, int colu

爪哇

在使用一个引用和两个整数作为参数进行10000次递归void函数调用后,出现堆栈溢出错误,这正常吗

获得6gb ram内存,尝试通过IDE和命令行运行。我很确定代码是正确的,递归应该完成

它是关于一个用于平铺贴图编辑器的填充工具。它从某个瓷砖开始,然后向上、向下、向右和向左移动,如果重合的瓷砖类型相同,并且没有返回

尝试了不同的方法,下面是一个附加布尔表,指示是否访问了[x][y]磁贴,并在递归完成后替换标记的磁贴:

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中使用大规模递归,您需要使用蹦床,它可以将堆栈空间交换为堆空间。蹦床通常有两种状态

  • 完成
  • 还有更多的工作要做
  • completed状态保存最终结果,可以使用供应商(在Java8中)或类似的构造来实现更多的工作,从而进行下一个递归调用。蹦床实现应该管理对方法的调用,并进行迭代而不是递归

    这是一个简单的蹦床打圈的例子

     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中使用大规模递归,您需要使用蹦床,它可以将堆栈空间交换为堆空间。蹦床通常有两种状态

  • 完成
  • 还有更多的工作要做
  • completed状态保存最终结果,可以使用供应商(在Java8中)或类似的构造来实现更多的工作,从而进行下一个递归调用。蹦床实现应该管理对方法的调用,并进行迭代而不是递归

    这是一个简单的蹦床打圈的例子

     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中使用大规模递归,您需要使用蹦床,它可以将堆栈空间交换为堆空间。蹦床通常有两种状态

  • 完成
  • 还有更多的工作要做
  • completed状态保存最终结果,可以使用供应商(在Java8中)或类似的构造来实现更多的工作,从而进行下一个递归调用。Trampoline实现应该管理对方法的调用,并迭代
     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();
    
    
             }
          };
      }
     }