Java:即使代码正确,递归也会导致堆栈溢出错误

Java: Recursion causes Stack Overflow Error even though code is correct

我正在尝试制作一个程序,它通过精灵图像,然后使其中的每个形状成为一个新图像。例如,如果我们拍马里奥,我希望帽子是一个图像,脸是另一个图像,等等。我已经让我的程序可以处理 32x32 的小图像,但是如果我想 运行 它用于更大的图像,它会导致堆栈溢出错误。如果我使用的是 C++,我会在每次递归调用后通过清除堆栈来解决这个问题,但据我所知,Java 不会让你直接清除堆栈。我希望我的程序在 Windows、Linux 和 Mac 上 运行 所以我认为 Java 是最好的选择,所以我真的不想切换我正在使用的语言。在 Java 中每次递归调用后,有没有办法删除存储在堆栈中的任何内容? 这是我的代码,以防出现错误。

 private void makeShape(int x, int y)
    {
        if(x < 0 || y < 0 || y >= sprite.getHeight() || x >= sprite.getWidth())
        {
            return;
        }
        if(sample == colorData[y][x] && table[y][x])
        {
            tempBlankImage[y][x] = sample;
            table[y][x] = false;
            makeShape(x, y - 1);
            makeShape(x, y + 1);
            makeShape(x - 1, y);
            makeShape(x + 1, y);
        }
        else
        {
            return;
        }

    }

x 点和 y 点由遍历图像的 for 循环生成,并检查是否已将点添加到形状中,如果没有,则根据其周围的像素创建形状。

更新:

    private int[][] makeShape(int sample, int x, int y)
    {
        int[][] tempBlankImage = blankImage();
        Queue<Point> queue = new LinkedList<Point>();
        queue.add(new Point(x,y));
        while(!queue.isEmpty())
        {
            Point point = queue.remove();
            if(sample == colorData[point.y][point.x] && table[point.y][point.x])
            {
                tempBlankImage[point.y][point.x] = sample;
                table[point.y][point.x] = false;
                if(point.y < sprite.getHeight() -1)
                    queue.add(new Point(point.x, point.y+1));
                if(point.y > 0)
                    queue.add(new Point(point.x, point.y-1));
                if(point.x < sprite.getWidth()-1)
                    queue.add(new Point(point.x+1, point.y));
                if(point.x > 0)
                    queue.add(new Point(point.x-1, point.y));
            }

        }
        queue = null;
        return tempBlankImage;
    }

堆栈溢出错误已停止,现在内存不足:Java 堆 Space,即使我将其增加到 2 GB。我将每个 int[][] 添加到 ArrayList,我猜这就是问题所在。我还能如何存储数据?

Java 以其 自动定义和测试的内存管理系统而闻名 - 自行管理内存通常不是个好主意,即使它是可能(因为在某种程度上它实际上是)。

如果算法执行时间能让你长出胡子并能给你的孙子讲故事,那么清除堆栈会给你带来什么?

不要将其设为递归 - 考虑算法的某种迭代形式。例如,您可以遍历所有图像的像素并将它们添加到适当的图像(由于它的颜色),这些图像将存储在一些 HashMap 中,就像这个 伪代码

    HashMap<Color, Image> images= new HashMap<Color, Image>();

    for(Pixel pixel : originImage)
        Color color = pixel.getColor();
        images.get(color).put(pixel)

不要为糟糕的代码浪费生命