为什么这个Java函数会崩溃?

时间:2016-10-19 22:50:44

标签: java algorithm memory-management heap-memory

我有一个简单的Java方法,它假设计算一定数量的素数除数列表。

public class Factors {



public static List<Integer> fac(List<Integer> factors, int number) {
    if(number < 2) {
        throw new IllegalArgumentException("Number must be greater than one");
    }


    for (int i = 2; i <= number; i++) {
        while (number%i == 0) {
            factors.add(i);
            number /= i;
        }
    }
    return factors;
}
public static void main(String [] args)
{
final long startTime = System.currentTimeMillis();

    ArrayList<Integer> factors = new ArrayList<>();
    System.out.println(fac(factors, 2147483647));

final long endTime = System.currentTimeMillis();
System.out.println("Total execution time: " + (endTime - startTime) );
}
}

此代码可以正常工作,除非您将Integer.MAX_VALUE提供给它;在这种情况下给予:
java.lang.OutOfMemoryError:Java堆空间
最初,我想,这是因为,ArrayList初始化在一个方法中,但在删除后,同样的错误仍然存​​在。
而且,这个:

public static List<Long> facrec2(List<Long> list, long number) {
    if (number < 2) {
        return list;
    }

    if (number == 2) {
        list.add(2L);
        return list;
    }

    for (long i = 2; i <= number; i++) {
        while (number % i == 0) {
            number /= i;
            list.add(i);
            return facrec2(list, number);
        }
    }
    return null;
}

方法适用于最大值(将签名更改为Integer后,也适用于整数最大值)。两者的逻辑假设是相同的,只有第二种的递归实现才有所不同......

2 个答案:

答案 0 :(得分:1)

for (int i = 2; i <= number; i++) {

问题出在这里。如果number == Integer.MAX_VALUE此循环永远不会终止。一旦i到达Integer.MAX_VALUE,下一个增量将其设置为Integer.MIN_VALUE,这是非常不利的,并且循环继续执行,因此您将继续永久添加到列表中并用完记忆

最简单的解决方案是将循环条件更改为<并处理number仍然具有其原始值的情况(即number为素数的情况)。您也可以在number == 1

之后退出循环

答案 1 :(得分:0)

此循环永不终止。当计数器i到达Integer.MAX_VALUE时,它会翻转。你不应该在循环条件中允许相等。