Android | 为什么有了ArrayMap还要再设计SparseArray?

两者区别:Key的类型

  • ArrayMap:通用Key类型
kotlin 复制代码
// ArrayMap - 支持任何Object作为Key
val arrayMap = ArrayMap<String, Any>()
arrayMap.put("name", "Alice")
arrayMap.put("age", 25)

val arrayMap2 = ArrayMap<Any, Any>()
arrayMap2.put(CustomObject(), "value")
  • SparseArray:专用 int Key 类型
kotlin 复制代码
// SparseArray - 只支持int作为Key
val sparseArray = SparseArray<String>()
sparseArray.put(100, "Alice")  // Key 必须是 int
sparseArray.put(200, "Bob")

// 变种版本
val sparseIntArray = SparseIntArray()
sparseIntArray.put(100, 25)    // Key=int, Value=int

为什么需要SparseArray?

1. 避免自动装箱

ArrayMap 的存储方式:

vbnet 复制代码
mHashes: [hash("100"), hash("200")]  // String 的哈希值
mArray:  ["100", "Alice", "200", "Bob"]  // Key 被存储为 String 对象

SparseArray 的存储方式:

arduino 复制代码
mKeys:   [100, 200]           // 直接存储原始 int
mValues: ["Alice", "Bob"]     // 值数组

性能对比:

kotlin 复制代码
// ArrayMap - 需要自动装箱
val arrayMap = ArrayMap<Any, Any>()
arrayMap.put(100, "value")  // 发生装箱:int → Integer
val value = arrayMap.get(100) // 可能发生拆箱

// SparseArray - 无装箱开销
val sparseArray = SparseArray<String>()
sparseArray.put(100, "value")  // 直接存储原始 int
val value = sparseArray.get(100) // 直接使用原始 int

2. 内存优化

SparseArray 系列专门优化:

kotlin 复制代码
// 不同的原始值类型,避免任何装箱
SparseIntArray()      // int → int
SparseLongArray()     // int → long  
SparseBooleanArray()  // int → boolean
SparseArray<String>() // int → String (只有值可能装箱)

3. 更简单的哈希计算

ArrayMap:

java 复制代码
// 需要计算任意对象的 hashCode
int hash = key.hashCode();
// 可能处理哈希冲突

SparseArray:

java 复制代码
// 直接使用 int 值本身,无需计算哈希
int key = 100; // 这就是"哈希值"
// 不会有哈希冲突(除非相同的 key)

实际使用场景对比

  • 适合 SparseArray 的场景:
kotlin 复制代码
// 1. View的ID映射
val viewMap = SparseArray<View>()
viewMap.put(R.id.button_submit, submitButton)
viewMap.put(R.id.text_title, titleView)

// 2. 位置索引映射
val itemMap = SparseArray<ListItem>()
itemMap.put(0, headerItem)
itemMap.put(5, specialItem)
  • 适合 ArrayMap 的场景:
kotlin 复制代码
// 1. 字符串键的配置
val config = ArrayMap<String, Any>()
config.put("server_url", "https://api.example.com")
config.put("timeout", 5000)

// 2. Bundle 数据存储
val bundleData = ArrayMap<String, Any?>()

// 3. 任意对象键的映射
val objectMap = ArrayMap<Any, String>()

性能对比总结

方面 SparseArray ArrayMap HashMap
int Key 内存 最优 ❌ 需要装箱 ❌ 需要装箱
Object Key 支持 ❌ 不支持 ✅ 支持 ✅ 支持
查找性能 ✅ O(log n) ✅ O(log n) ✅ O(1)
插入性能 ⚠️ O(n) ⚠️ O(n) ✅ O(1)
内存占用 最低 ✅ 较低 ❌ 较高
  • SparseArray :为 int → Object 这种特定场景提供优化
  • ArrayMap :为通用的 Object → Object 映射提供平衡优化
  • HashMap :为大数据量高性能场景提供通用解决方案
相关推荐
limuyang24 小时前
PDF Viewer KMP(基于 chrome 的 PDFium 内核)
android·kotlin
心平气和量大福大8 小时前
android-控件-搜索框SearchView
android·gitee
2601_962177138 小时前
【MySQL篇】聚合查询,联合查询
android·java·mysql
壮哥_icon8 小时前
【Android】批量 VectorDrawable 动态分别修改 fillColor 和 strokeColor 的踩坑与终极解决方案
android
齐天qaq9 小时前
Android 系统 APK 分区与权限
android
心平气和量大福大9 小时前
android-控件-多选框CheckBox
android·gitee
pengyu11 小时前
【Kotlin 协程修仙录 · 大乘境 · 初阶】 | 跳出三界:协程在 KMP 与后端开发中的跨平台之道
android·kotlin
XiaoLeisj11 小时前
Android Memory Profiler:堆内存指标、内存抖动与泄漏定位
android·性能优化·内存抖动·内存泄露·memory profiler
未来猫咪花11 小时前
Everything is ViewModel:让状态管理回到对象世界
android·flutter·ios