繁体   English   中英

Java中的StackOverflowError,同时使用数组和递归

[英]StackOverflowError in Java while working with arrays and recursion

我的MatrixCreatureContainer类中的lifeCycle方法在大约3-4k迭代后引发了堆栈溢出错误。 这是为什么? 我认为这与内存分配有关,但是我无法弄清楚如何解决它。 我尝试阅读有关Java垃圾收集器的信息,但似乎没有帮助。

public class MatrixCreatureContainer {

    private final static int NUMBER_OF_CREATURES = 20;
    private static Random rand;

    public static void main(String[] args){

        rand = new Random();
        List<MatrixCreature> population = new ArrayList<MatrixCreature>();

        for(int i = 0; i < NUMBER_OF_CREATURES ; i++){
            population.add(new MatrixCreature());
        }

        Collections.sort(population);

        lifeCycle(population,0, 4000);
    }

    private static void lifeCycle(List<MatrixCreature> population, int generation, int iterations){

        if (generation == iterations) return;

        List<MatrixCreature> newPopulation = new ArrayList<MatrixCreature>();

        while(population.size() != 0){
            MatrixCreature mother = population.remove(rand.nextInt(population.size()));
            MatrixCreature father = population.remove(rand.nextInt(population.size()));
            newPopulation.add(new MatrixCreature(mother,father));
            newPopulation.add(new MatrixCreature(mother,father));
            newPopulation.add(new MatrixCreature(mother,father));
        }

        Collections.sort(newPopulation);

        newPopulation = newPopulation.subList(0,NUMBER_OF_CREATURES);

        lifeCycle(newPopulation,generation + 1, iterations);

    }

} 

MatrixCreature类基本上仅包含20个整数的整数数组(int [])。 构造函数接受其他两个matrixCreatures,并将给出的两个matrixCreatures的数组组合在一起,发生突变的机会很小。 每个matrixCreature都会得到一个分数(其中0为最佳),该分数表示数组中的数字总和与55的接近程度。得分是对MatrixCreatureContainer中每一代的总体进行排序的,因此20个“最佳”的每一代都可以生存。
如果相关,我可以将代码发布到MatrixCreature类。

提前致谢 :)

-Boye

通过此调用:

lifeCycle(population,0, 4000);

您基本上是在要求具有4000帧的堆栈(至少-稍后再介绍)。 这并不是完全没有道理的,但是实际上根本没有理由进行这种递归。 您可以轻松地将方法更改为迭代-甚至删除generation参数:

private static void lifeCycle(List<MatrixCreature> population, int iterations) {
    for (int generation = 0; generation < iterations; generation++) {
        // Body of previous method here
    }
}

此外,您继续使用newPopulation = newPopulation.subList(...)创建视图。 您可能不想这样做-这意味着每个操作都需要遍历大量堆栈帧,因为对视图的每次调用都将委托给其基础列表...如果是另一个视图,则需要继续前进,等等。 如果这些视图调用实际上每个“层”都需要几个堆栈帧,那么您可能很容易在原始代码中得到大约12,000个调用堆栈。

我建议改为在每次迭代时创建列表相关部分的副本 -然后返回最终列表。

每个生命周期都以自己的population起点,并为下一代创造一个新population (内部始终有3个生物;这是意图吗?)

因此,经过4000次迭代之后,您就可以找到那4000个人口列表,因为它们从未超出范围。

Java不支持尾递归优化,因此lifeCycle方法的最后一行为每次迭代创建一个新的堆栈框架。

根据您的内存大小和局部变量的数量,您已经确定可以拥有大约4000个堆栈帧。 解决方案:使用for循环重写您的方法。 这是一个很小的变化,您的方法实际上不需要递归。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM