I can think of several reasons why HashMap
s with integer keys are much better than SparseArray
s:
SparseArray
says "It is generally slower than a traditional HashMap
".HashMap
s rather than SparseArray
s your code will work with other implementations of Map and you will be able to use all of the Java APIs designed for Maps.HashMap
s rather than SparseArray
s your code will work in non-android projects.equals()
and hashCode()
whereas SparseArray
doesn't.Yet whenever I try to use a HashMap
with integer keys in an Android project, IntelliJ tells me I should use a SparseArray
instead. I find this really difficult to understand. Does anyone know any compelling reasons for using SparseArray
s?
SparseArray
can be used to replace HashMap
when the key is a primitive type.
There are some variants for different key/value types, even though not all of them are publicly available.
Benefits are:
Drawbacks:
HashMap
can be replaced by the following:
SparseArray <Integer, Object>
SparseBooleanArray <Integer, Boolean>
SparseIntArray <Integer, Integer>
SparseLongArray <Integer, Long>
LongSparseArray <Long, Object>
LongSparseLongArray <Long, Long> //this is not a public class
//but can be copied from Android source code
In terms of memory, here is an example of SparseIntArray
vs HashMap<Integer, Integer>
for 1000 elements:
SparseIntArray
:
class SparseIntArray {
int[] keys;
int[] values;
int size;
}
Class = 12 + 3 * 4 = 24 bytes
Array = 20 + 1000 * 4 = 4024 bytes
Total = 8,072 bytes
HashMap
:
class HashMap<K, V> {
Entry<K, V>[] table;
Entry<K, V> forNull;
int size;
int modCount;
int threshold;
Set<K> keys
Set<Entry<K, V>> entries;
Collection<V> values;
}
Class = 12 + 8 * 4 = 48 bytes
Entry = 32 + 16 + 16 = 64 bytes
Array = 20 + 1000 * 64 = 64024 bytes
Total = 64,136 bytes
Source: Android Memories by Romain Guy from slide 90.
The numbers above are the amount of memory (in bytes) allocated on heap by JVM. They may vary depending on the specific JVM used.
The java.lang.instrument
package contains some helpful methods for advanced operations like checking the size of an object with getObjectSize(Object objectToSize)
.
Extra info is available from the official Oracle documentation.
Class = 12 bytes + (n instance variables) * 4 bytes
Array = 20 bytes + (n elements) * (element size)
Entry = 32 bytes + (1st element size) + (2nd element size)