【发布时间】:2017-09-27 15:25:11
【问题描述】:
我正在对 Java 进行一些修改,但在其他一些语言方面有很多经验。 我有一个我知道解决方案的测试问题(并且可以很容易地用 Python 和 C++ 生成)。但是运行下面的 Java 代码会给出一个
线程“主”java.lang.OutOfMemoryError 中的异常:Java 堆空间
我想知道我是否犯了一个简单的错误,我不希望这个程序的内存占用非常大:
public static void main(String[] args) {
ArrayList<Integer> longest_sequence = new ArrayList<>();
ArrayList<Integer> this_sequence;
int n = 0;
for (int i = 1; i < 1000000; i++) {
this_sequence = new ArrayList<Integer>();
n = i;
this_sequence.add(n);
while (n != 1) {
if (n % 2 == 0) {
n = n / 2;
}
else {
n = 3*n + 1;
}
this_sequence.add(n);
}
if (this_sequence.size() > longest_sequence.size()) {
longest_sequence = this_sequence;
}
}
System.out.println(longest_sequence.get(0));
System.out.println(longest_sequence.size());
}
澄清一点:
在程序的每次迭代中都会创建一个新列表。它要么通过为其分配最长的序列来保留,要么被新的列表实例丢弃并覆盖。
我猜我对此的假设不正确,并且正在保留实例?列表的大小应该不是问题(最大的大约有 500 个元素)。
【问题讨论】:
-
您可以尝试增加正在运行的程序的堆空间。它可能默认小于1G
-
尝试使用
this_sequence.clear(),并且只使用一个对列表的引用,而不是在循环中重新创建 -
可能因为你的while循环,内存占用会很大,你怎么知道最大的有多大?
-
您对代码所需的堆内存的估计是多少?
-
这里的问题是整数溢出并且你的 Collatz 猜想代码没有像你期望的那样在 1 处终止。将
int替换为long,一切都很好。当然,这仍然是一种非常低效的测量序列长度的方法,根本不需要在内存中保存任何内容。
标签: java jvm out-of-memory heap-memory