想看我更多文章:【张旭童的博客】http://blog.csdn.net/zxt0601
想来gayhub和我gaygayup:【mcxtzhang的Github主页】https://github.com/mcxtzhang
1 概述
在前文中,我们已经聊过了HashMap
和LinkedHashMap
ArrayMap
.所以如果没看过,可以先阅读
面试必备:HashMap源码解析(JDK8) ,
面试必备:LinkedHashMap源码解析(JDK8 ,
面试必备:ArrayMap源码解析
今天依旧是看看android sdk的源码。
本文将从几个常用方法下手,来阅读SparseArray
的源码。
按照从构造方法->常用API(增、删、改、查)的顺序来阅读源码,并会讲解阅读方法中涉及的一些变量的意义。了解SparseArray
的特点、适用场景。
如果本文中有不正确的结论、说法,请大家提出和我讨论,共同进步,谢谢。
2 概要
概括的说,SparseArray<E>
是用于在Android平台上替代HashMap
的数据结构,更具体的说,
是用于替代key
为int
类型,value
为Object
类型的HashMap
。
和ArrayMap
类似,它的实现相比于HashMap
更加节省空间,而且由于key指定为int
类型,也可以节省int
-Integer
的装箱拆箱操作带来的性能消耗。
它仅仅实现了implements Cloneable
接口,所以使用时不能用Map
作为声明类型来使用。
它也是线程不安全的,允许value为null。
从原理上说,
它的内部实现也是基于两个数组。
一个int[]
数组mKeys
,用于保存每个item的key
,key
本身就是int
类型,所以可以理解hashCode
值就是key
的值.
一个Object[]
数组mValues
,保存value
。容量和key
数组的一样。
类似ArrayMap
,
它扩容的更合适,扩容时只需要数组拷贝工作,不需要重建哈希表。
同样它不适合大容量的数据存储。存储大量数据时,它的性能将退化至少50%。
比传统的HashMap
时间效率低。
因为其会对key从小到大排序,使用二分法查询key对应在数组中的下标。
在添加、删除、查找数据的时候都是先使用二分查找法得到相应的index,然后通过index来进行添加、查找、删除等操作。
所以其是按照key
的大小排序存储的。
另外,SparseArray
为了提升性能,在删除操作时做了一些优化:
当删除一个元素时,并不是立即从value
数组中删除它,并压缩数组,
而是将其在value
数组中标记为已删除。这样当存储相同的key
的value
时,可以重用这个空间。
如果该空间没有被重用,随后将在合适的时机里执行gc(垃圾收集)操作,将数组压缩,以免浪费空间。
适用场景:
- 数据量不大(千以内)
- 空间比时间重要
- 需要使用
Map
,且key
为int
类型。
示例代码:
SparseArray<String> stringSparseArray = new SparseArray<>();
stringSparseArray.put(1,"a");
stringSparseArray.put(5,"e");
stringSparseArray.put(4,"d");
stringSparseArray.put(10,"h");
stringSparseArray.put(2,null);
Log.d(TAG, "onCreate() called with: stringSparseArray = [" + stringSparseArray + "]")