Sitemap

HashMap, ArrayMap and SparseArray

5 min readAug 17, 2024

--

HashMap

A HashMap is a data structure used to store key-value pairs. It’s a fundamental part of the Java and Android development ecosystem. In Android, it’s widely used to efficiently store and retrieve data.

Key Characteristics:

  • Stores key-value pairs: Each element in a HashMap consists of a key and a corresponding value.
  • Unordered: Elements in a HashMap are not stored in any particular order.
  • Efficient retrieval: Values can be accessed quickly using their associated keys.
  • Allows null keys and values: A HashMap can contain null keys and null values.
  • Implementation: It’s based on a hash table, which uses a hash function to map keys to indices in an array.

Common Use Cases in Android:

  • Storing configuration settings
  • Caching data
  • Mapping objects to identifiers
  • Implementing custom data structures
fun main() {
val hashMap = HashMap<String, Int>() // Create a HashMap with String keys and Int values

// Adding elements
hashMap["apple"] = 3
hashMap.put("banana", 5)
hashMap.put("orange", 2)

// Accessing values
println(hashMap["apple"]) // Output: 3
println(hashMap.get("banana")) // Output: 5

// Checking if a key exists
println(hashMap.containsKey("grape")) // Output: false

// Iterating through the HashMap
for ((key, value) in hashMap) {
println("$key -> $value")
}
}
}

Common Methods

Adding Elements

  • put(key, value): Adds a key-value pair to the map. If the key already exists, the old value is replaced.

Retrieving Values

  • get(key): Returns the value associated with the given key, or null if the key is not present.
  • containsKey(key): Checks if the map contains the specified key.
  • containsValue(value): Checks if the map contains the specified value.

Removing Elements

  • remove(key): Removes the mapping for the specified key from this map if present.
  • clear(): Removes all mappings from this map.

Iterating Over Elements

  • entries(): Returns a set of all entries in this map.
  • keys(): Returns a set of all keys in this map.
  • values(): Returns a collection of all values in this map.

Other Useful Methods

  • size(): Returns the number of key-value pairs in the map.
  • isEmpty(): Returns true if the map contains no key-value pairs.
  • putAll(map): Copies all of the mappings from the specified map to this map.
fun main() {
val hashMap = HashMap<String, Int>()
// ... populate the HashMap

// Removing an element
hashMap.remove("banana")

// Checking if a value exists
println(hashMap.containsValue(3)) // Output: true

// Getting all keys
val keys = hashMap.keys
println(keys) // Output: [apple, orange]

// Getting all values
val values = hashMap.values
println(values) // Output: [3, 2]

// Clearing the HashMap
hashMap.clear()
println(hashMap.isEmpty()) // Output: true
}

Immutable HashMaps

  • Immutable: A data structure that cannot be changed once created.
  • Read-only: A data structure that appears immutable from the outside but might be mutable internally.

Achieving Immutability in Kotlin

  1. Using mapOf:
  • Creates an immutable map directly:
val immutableMap = mapOf("key1" to "value1", "key2" to "value2")
  • Any attempt to modify this map will result in a compilation error.

2. Creating a Read-Only View:

  • Convert a mutable map to a read-only view:
val mutableMap = mutableMapOf("key1" to "value1")
val immutableView = mutableMap.toMap() // Creates a read-only view
  • Modifying the original mutableMap will affect the immutableView.

3. Creating a New Map for Modifications:

  • When changes are needed, create a new map instead of modifying the existing one:
val newMap = immutableMap + ("key3" to "value3")

Example:

fun main() {
val immutableMap = mapOf("name" to "Alice", "age" to 30)
println(immutableMap) // Output: {name=Alice, age=30}

// Attempt to modify (will result in a compilation error)
// immutableMap["city"] = "New York"

val newMap = immutableMap + ("city" to "New York")
println(newMap) // Output: {name=Alice, age=30, city=New York}
}

ArrayMap

ArrayMap is a data structure provided by the Android framework that efficiently stores key-value pairs. It’s optimized for situations where you have a relatively small number of elements and performance is critical.

Get Anna’s stories in your inbox

Join Medium for free to get updates from this writer.

Key differences from HashMap:

  • Memory efficiency: ArrayMap often uses less memory than HashMap, especially for smaller datasets.
  • Performance: ArrayMap can be faster than HashMap for certain operations, particularly when the number of elements is small.
  • Order preservation: Unlike HashMap, ArrayMap maintains insertion order.

When to Use ArrayMap

  • Small datasets: When you expect a limited number of key-value pairs.
  • Performance-critical scenarios: In situations where memory efficiency and speed are paramount.
  • Order preservation: If you need to iterate over the elements in the same order they were inserted.

Key Methods and Usage

fun main() {
val myArrayMap = ArrayMap<String, Int>()

// Adding elements
myArrayMap["apple"] = 5
myArrayMap.put("banana", 3)
myArrayMap.put("orange", 2)

// Accessing values
val appleCount = myArrayMap["apple"] // Returns 5
println("Apple count: $appleCount")

// Iterating through the map
for ((key, value) in myArrayMap) {
println("$key: $value")
}

// Removing elements
myArrayMap.remove("banana")

// Checking if a key exists
val containsOrange = myArrayMap.containsKey("orange") // Returns true
println("Contains orange: $containsOrange")
}

SparseArray

SparseArray is a data structure provided by the Android platform that efficiently maps integer keys to values. It’s specifically designed for scenarios where you have a large number of keys but only a small subset of them actually have corresponding values.

Key Characteristics:

  • Integer keys: It exclusively uses integer values as keys.
  • Efficient storage: Optimized for sparse data sets, where many potential keys don’t have associated values.
  • Performance: Generally faster than HashMap for integer keys and sparse data.
  • Android-specific: Primarily used in Android development due to its performance benefits.
import android.util.SparseArray

fun main() {
val sparseArray = SparseArray<String>()

// Insert key-value pairs
sparseArray.put(1, "One")
sparseArray.put(3, "Three")

// Access values
val value1 = sparseArray.get(1) // Returns "One"
val value2 = sparseArray.get(2) // Returns null

// Remove a key-value pair
sparseArray.remove(3)

// Check if a key exists
val containsKey = sparseArray.indexOfKey(1) != -1 // Returns true
}

Key Differences and When to Use Which

HashMap, ArrayMap and SparseArray

When to use which:

  • HashMap: Use for general-purpose mapping when key type flexibility is essential and memory efficiency is not a primary concern.
  • ArrayMap: Use for most key-value mappings in Android applications due to its balance of performance and memory efficiency.
  • SparseArray: Use when dealing with integer keys and memory optimization is critical, such as storing large datasets with integer indices.

If you find errors or you think something important is missing, please report them in the comments. Also, let us know what other scenarios you would like us to write about.

Thanks for Reading ❤

Anna

--

--