2

I have a similar code:

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);
}

Sometimes happen that in older Android device, this code leads to OutOfMemory on new HashMap.

There is a way to improve this code? Thanks

EDIT:

I have this structure in my Application Class to retrive this array around the app and do something like that:

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));
asked Jun 3, 2016 at 11:59
10
  • try this on codereview Commented Jun 3, 2016 at 12:03
  • Why do you need a list of 8000 identical hashmaps? Commented Jun 3, 2016 at 12:05
  • @zapl "similar code" string1 and string2 are always different for each i Commented Jun 3, 2016 at 12:07
  • FYI This is not a memory leak, this is out of memory. Commented Jun 3, 2016 at 12:07
  • 2
    This isn't really "leaking" memory, is it? You're just creating a bunch of hash maps, and then storing them in a list. Assuming you keep hold of myArray, the hash maps (and the list) aren't eligible for GC. Commented Jun 3, 2016 at 12:08

5 Answers 5

1

You can improve your code a bit, I'll write two solutions, the first is better, but if you can't use it, use the second one:

In both solutions, use a constructor with initial capacity.

Use SparseArray if you can change your keys in int values:

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);
}

Use ArrayMap instead:

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);
}
answered Jun 3, 2016 at 12:11
6
  • thanks for your answer, why ArrayMap is better than HashMap? Commented Jun 3, 2016 at 12:17
  • @Ilario because HashMap creates an object (Entry) for each pair of key/value. Instead, ArrayMap creates an array of key and an array of values. Commented Jun 3, 2016 at 12:22
  • @Ilario ArrayMap is added in api 19 but is available also on api 9 Commented Jun 3, 2016 at 12:29
  • @Fondesa but Android Studio tell me "call requires Api level 19 (current min is 9) Commented Jun 3, 2016 at 12:33
  • @Ilario you have to import android.support.v4.util.ArrayMap not android.util.ArrayMap Commented Jun 3, 2016 at 12:36
1

my answer is coming from here

why not to create an object that holds your properties

like this

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);
 } 

what i'm trying to say here that the hashmap object has an overhead that can be shrinked using an object

answered Jun 3, 2016 at 12:06
1

You code should be changed to:

String[] stringObj1 = new String[myArray.size()]);
String[] stringObj2 = new String[myArray.size()]);
for (int i = 0; i < myArray.size(); i++) {
 stringObj1[i] = myArray.get(i).get("key1");
 stringObj2[i] = myArray.get(i).get("key2");
}
list.setAdapter(new Adapter(this, stringObj1, stringObj2));

This prevents the intermediate lists and saves memory. The copy operation does not start if the memory for the two arrays is not available.

myArray does not seems to be an array but a list. :o

answered Jun 3, 2016 at 14:08
1
  • thanks for your answer, myarray is this ArrayList<ArrayMap<String, String>> myArray = new ArrayList<ArrayMap<String, String>>(); Commented Jun 3, 2016 at 14:11
0

What You have done is good enough. the only concern is the device doesnt have that much memory to allocate for new hashmap object every time.

When you start JVM you define how much RAM it can use use for processing. JVM divides this into certain memory locations for its processing purpose, two of those are Stack & Heap

OutOfMemoryError is related to Heap. If you have large objects (or) referenced objects in memeory, then you will see OutofMemoryError. If you have strong references to objects, then GC can't clean the memory space allocated for that object. When JVM tries to allocate memory for new object and not enough space available it throws OutofMemoryError because it can't allocate required amount of memory.

How to avoid: Make sure un-necessary objects are available for GC

StackOverflowError is related to stack. All your local variables and methods calls related data will be on stack. For every method call one stack frame will be created and local as well as method call related data will be placed inside the stack frame. Once method execution is completed, stack frame will be removed. ONE WAY to reproduce this is, have infinite loop for method call, you will see stackoverflow error, because stack frame will be populated with method data for every call but it won't be freed (removed).

How to avoid Make sure method calls are ending (not in infinite loop)

answered Jun 3, 2016 at 12:21
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);
} 

Do like this declare hashMap outside for loop. you are creating object again and again in memory pool.

Nicolas Filotto
45.2k11 gold badges97 silver badges129 bronze badges
answered Jun 3, 2016 at 12:04
3
  • you create a list of the same instance of HashMap, the result is not what the OP expect Commented Jun 3, 2016 at 12:10
  • This is very different to what OP is doing in his/her code. Commented Jun 3, 2016 at 12:11
  • I have give you solution for out of memory exception .. not what you want as output,, for your OP put a different question or edit your quetion Commented Jun 3, 2016 at 12:16

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.