HashMap进入ArrayList Out of Memory

时间:2016-06-03 11:59:07

标签: java android arraylist hashmap

我有类似的代码:

ArrayList<HashMap<String, String>> myArray = new ArrayList<HashMap<String, String>>();

for(int i=0; i<8000; i++){

  HashMap <String, String> hashMap = new HashMap<String, String>();

  hashMap.put("key1", string1);
  hashMap.put("key2", string2);

  myArray.add(hashMap);
}

有时会发生在较旧的Android设备中,此代码会导致new HashMap上的OutOfMemory。

有一种方法可以改进这段代码吗? 感谢

修改

我在我的应用程序类中有这个结构来围绕应用程序检索这个数组并执行类似的操作:

ArrayList<String> allObj1 = new ArrayList<String>();
ArrayList<String> allObj2 = new ArrayList<String>();

for (int i = 0; i<myArray.size(); i++) {

    String obj1 = myArray.get(i).get("key1");
    String obj2 = myArray.get(i).get("key2");

    allObj1.add(obj1);
    allObj2.add(obj2);
 }


 String[] stringObj1 = allObj1.toArray(new String[allObj1.size()]);
 String[] stringObj2 = allObj2.toArray(new String[allObj2.size()]);

 list.setAdapter(new Adapter(this, stringObj1, stringObj2));

5 个答案:

答案 0 :(得分:1)

我的回答来自here

为什么不创建一个包含属性的对象

像这样

class A{
String key1;
String key2;
}
 ArrayList<A> myArray = new ArrayList<A>();
for(int i=0; i<8000; i++) {
    A a=new A();
    a.key1=string1;
    a.key2=string2;
    myArray.Add(a);
 } 

我在这里想说的是,hashmap对象有一个可以使用对象缩小的开销

答案 1 :(得分:1)

你可以稍微改进你的代码,我会写两个解决方案,第一个更好,但如果你不能使用它,请使用第二个:

在两个解决方案中,使用具有初始容量的构造函数。

如果您可以更改int值中的键,请使用SparseArray

ArrayList<SparseArray<String>> myArray = new ArrayList<>(8000);
for(int i=0; i<8000; i++) {
    SparseArray<String> sp = new SparseArray<>(2);
    sp.put(1, string1);
    sp.put(2, string2);
    myArray.add(sp);
}

改为使用ArrayMap

ArrayList<ArrayMap<String, String>> myArray = new ArrayList<>(8000);
for (int i = 0; i < 8000; i++) {
    ArrayMap<String, String> am = new ArrayMap<>(2);
    am.put("key1", string1);
    am.put("key2", string2);
    myArray.add(am);
}

答案 2 :(得分:1)

您的代码应更改为:

siftDown()

这可以防止中间列表并节省内存。如果两个阵列的内存不可用,则不会启动复制操作。

myArray似乎不是数组而是列表。 :○

答案 3 :(得分:0)

ArrayList<HashMap<String, String>> myArray = new ArrayList<HashMap<String, String>>();
HashMap <String, String> hashMap = new HashMap<String, String>();
for(int i=0; i<8000; i++) {     
    hashMap.put("key1", string1);
    hashMap.put("key2", string2); 
    myArray.add(hashMap);
} 

这样做声明hashMap在for循环之外。你在内存池中一次又一次地创建对象。

答案 4 :(得分:0)

你所做的就是足够好。唯一的问题是设备每次都没有为新的hashmap对象分配那么多内存。

启动JVM时,您可以定义可用于处理的RAM量。 JVM将其划分为某些存储位置以用于其处理目的,其中两个是Stack&amp; amp;堆

OutOfMemoryError与Heap有关。如果在memeory中有大对象(或)引用的对象,那么您将看到OutofMemoryError。如果您对对象有强引用,则GC无法清除为该对象分配的内存空间。当JVM尝试为新对象分配内存而没有足够的可用空间时,它会抛出OutofMemoryError,因为它无法分配所需的内存量。

如何避免:确保GC具有不必要的对象

StackOverflowError与堆栈有关。所有局部变量和方法调用相关数据都将在堆栈中。对于每个方法调用,将创建一个堆栈帧,并且本地以及与方法调用相关的数据将被放置在堆栈帧内。方法执行完成后,将删除堆栈帧。重现这一点的一种方法是,对于方法调用有无限循环,你会看到stackoverflow错误,因为堆栈帧将填充每个调用的方法数据,但它不会被释放(删除)。

如何避免确保方法调用结束(不是无限循环)