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));
5 Answers 5
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);
}
-
thanks for your answer, why ArrayMap is better than HashMap?Ilario– Ilario2016年06月03日 12:17:25 +00:00Commented 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.Giorgio Antonioli– Giorgio Antonioli2016年06月03日 12:22:36 +00:00Commented Jun 3, 2016 at 12:22 -
@Ilario
ArrayMap
is added in api 19 but is available also on api 9Giorgio Antonioli– Giorgio Antonioli2016年06月03日 12:29:22 +00:00Commented Jun 3, 2016 at 12:29 -
@Fondesa but Android Studio tell me "call requires Api level 19 (current min is 9)Ilario– Ilario2016年06月03日 12:33:12 +00:00Commented Jun 3, 2016 at 12:33
-
@Ilario you have to import
android.support.v4.util.ArrayMap
notandroid.util.ArrayMap
Giorgio Antonioli– Giorgio Antonioli2016年06月03日 12:36:48 +00:00Commented Jun 3, 2016 at 12:36
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
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
-
thanks for your answer, myarray is this ArrayList<ArrayMap<String, String>> myArray = new ArrayList<ArrayMap<String, String>>();Ilario– Ilario2016年06月03日 14:11:15 +00:00Commented Jun 3, 2016 at 14:11
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)
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.
-
you create a list of the same instance of HashMap, the result is not what the OP expectNicolas Filotto– Nicolas Filotto2016年06月03日 12:10:12 +00:00Commented Jun 3, 2016 at 12:10
-
This is very different to what OP is doing in his/her code.Andy Turner– Andy Turner2016年06月03日 12:11:43 +00:00Commented 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 quetionJishant– Jishant2016年06月03日 12:16:18 +00:00Commented Jun 3, 2016 at 12:16
myArray
, the hash maps (and the list) aren't eligible for GC.