我试图通过填充超过百万行来计算Arraylist和Linkedlist,并在Arraylist人口之后得到以下错误,
线程“main”中的异常java.lang.OutOfMemoryError:Java堆空间 在java.lang.Integer.valueOf(Integer.java:642) at scratch.Collectionss.main(Collectionss.java:25)
如何避免此错误,我尝试设置l1 = null但这会给我一个错误,
public class Collectionss {
public static void main(String[] args){
//
long starttime = System.currentTimeMillis();
List<Integer> l1 = new ArrayList<Integer>();
for (int i = 1; i <= 10000000; i++){
l1.add(i);
}
System.out.println(l1.size());
long endtime = System.currentTimeMillis();
System.out.println(endtime - starttime);
//
long starttime1 = System.currentTimeMillis();
List<Integer> l2 = new LinkedList<Integer>();
for (int i = 1; i <= 10000000; i++){
l2.add(i);
}
System.out.println(l2.size());
long endtime1 = System.currentTimeMillis();
System.out.println(endtime1 - starttime1);
}
}
答案 0 :(得分:6)
你应该在不同的方法中运行这些测试,因为第一个循环的优化会干扰第二个循环的优化,即第二个循环可能更慢,只是因为它是第二个。
我建议您至少运行10次(或2秒)并使用具有更高分辨率的System.nanoTime()。
如果你这样做但仍然内存不足,我建议你增加最大内存大小。如果您运行的是32位窗口,则默认值非常低。您可以在命令行上使用-Xmx1g
增加它
如果您执行以下操作,您可以看到GC具有最大的影响,这并不奇怪,因为问题最常产生垃圾
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class Collectionss {
public static final int TO_ADD = 10000000;
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
long timeAL = timeAddToArrayList();
long timeLL = timeAddsToLinkedList();
System.out.printf("Time to add %,d Integer to ArrayList %.3f sec, LinkedList %.3f%n",
TO_ADD, timeAL / 1e9, timeLL / 1e9);
}
}
private static long timeAddToArrayList() {
long starttime = System.nanoTime();
List<Integer> l1 = new ArrayList<Integer>();
for (int i = 1; i <= TO_ADD; i++) {
l1.add(i);
}
assert TO_ADD == l1.size();
return System.nanoTime() - starttime;
}
private static long timeAddsToLinkedList() {
long starttime = System.nanoTime();
List<Integer> l2 = new LinkedList<Integer>();
for (int i = 1; i <= TO_ADD; i++) {
l2.add(i);
}
assert TO_ADD == l2.size();
return System.nanoTime() - starttime;
}
}
打印
Time to add 10,000,000 Integer to ArrayList 0.238 sec, LinkedList 1.326
Time to add 10,000,000 Integer to ArrayList 1.193 sec, LinkedList 0.971
Time to add 10,000,000 Integer to ArrayList 0.841 sec, LinkedList 0.048
Time to add 10,000,000 Integer to ArrayList 0.349 sec, LinkedList 1.128
Time to add 10,000,000 Integer to ArrayList 0.064 sec, LinkedList 0.048
然而,在每次测试之前添加System.gc()并获得
Time to add 10,000,000 Integer to ArrayList 0.241 sec, LinkedList 2.130
Time to add 10,000,000 Integer to ArrayList 0.070 sec, LinkedList 0.072
Time to add 10,000,000 Integer to ArrayList 0.067 sec, LinkedList 0.053
Time to add 10,000,000 Integer to ArrayList 0.069 sec, LinkedList 0.048
Time to add 10,000,000 Integer to ArrayList 0.065 sec, LinkedList 0.051
答案 1 :(得分:2)
尝试增加堆大小并运行程序
答案 2 :(得分:1)
您需要通过-Xmx4g
标志增加可用于JVM的堆。
这会将堆大小增加到4GB。您不需要命令行。 IDE还接受JVM参数。 E. g。日食:Run Configurations... -> Arguments -> VM Arguments
正如@crush提到的,如果你初始化,你可以节省内存(分别是GC的一些工作)
具有所需容量的ArrayList
。
答案 3 :(得分:1)
我认为您可以在运行程序时指定堆大小。如果您在命令行上执行,则每当使用“java”执行时都包含一个参数:“ - Xms1024m -Xmx1024m”或您希望堆大小的任何内容。查看jvm启动参数以获得确切的用法。
答案 4 :(得分:0)
您在List集合中添加了10000000个项目。每次都肯定会增加内存消耗并最终超过堆大小。
你正在创造这样一个集合两次。
你需要弄清楚为什么你需要这么大的收藏品。如果您需要这么大的集合,那么您需要增加所需的堆空间。
答案 5 :(得分:0)
如果您正在处理大型数据集,那么在您的情况下,最好使用正确的大小初始化ArrayList
。
List<Integer> l1 = new ArrayList<Integer>(10000000);
,否则您的ArrayList
的默认大小为10
,每次超过大小时,add
方法都会创建一个新的array
{1}}复制array
内arraylist
内旧版ArrayList ensureCapacity
的所有内容。{/}
请参阅if (minCapacity > oldCapacity) {
Object oldData[] = elementData;
int newCapacity = (oldCapacity * 3)/2 + 1;
if (newCapacity < minCapacity)
newCapacity = minCapacity;
// minCapacity is usually close to size, so this is a win:
**elementData = Arrays.copyOf(elementData, newCapacity);**
}
方法中的以下来源。
{{1}}
如果它仍然发生,即使在初始化之后,也会像其他人在帖子中建议的那样增加堆大小。