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> with android.util.SparseArray<V>.

  • For primitive value types use the dedicated variants: SparseIntArray, SparseLongArray, SparseBooleanArray.

  • Keep Map only when the API contract requires MutableMap (e.g. interoperability with Java code that does not depend on Android).