Android Sparse Arrays
ID |
kotlin.android_sparse_arrays |
Severity |
info |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Efficiency |
Language |
Kotlin |
Tags |
android, best-practice, efficiency |
Description
Reports Map, MutableMap, HashMap, LinkedHashMap, TreeMap, or ConcurrentHashMap
usages whose key type argument is Int / Integer. On Android, SparseArray (or
SparseIntArray, SparseLongArray, SparseBooleanArray) is significantly more
memory-efficient than a Map keyed by a boxed Integer, because the autobox of the key
on every get / put is eliminated.
Rationale
val cache: Map<Int, String> = mutableMapOf() // FLAW
private val items = HashMap<Int, Bitmap>() // FLAW
fun byId(): MutableMap<Int, Item> = mutableMapOf() // FLAW
val byName: Map<String, Int> = mutableMapOf() // OK — String key
val byLong: Map<Long, String> = mutableMapOf() // OK — non-Int key
Each Map<Int, V> operation boxes the Int key into a heap-allocated Integer, churning
the young generation and slowing lookup. SparseArray keeps the keys as primitive int
and stores values in parallel arrays, trading O(log n) binary-search lookup for zero
allocation and dramatically smaller memory footprint.
Remediation
-
Replace
Map<Int, V>withandroid.util.SparseArray<V>. -
For primitive value types use the dedicated variants:
SparseIntArray,SparseLongArray,SparseBooleanArray. -
Keep
Maponly when the API contract requiresMutableMap(e.g. interoperability with Java code that does not depend on Android).