浅析SparseArray的源码实现

本文深入解析SparseArray集合类,探讨其与HashMap的区别,包括key类型、内存占用、逻辑复杂度及性能对比。通过代码示例,详细阐述SparseArray的内部实现原理,包括增删查改操作及垃圾回收机制。
前言:

在我们学习一个新技术,新东西之前,我们往往会先考虑到以下几个问题:

  1. SparseArray是什么?
  2. SparseArray有什么优点和缺点?
  3. SparseArray是如何实现这些优点?
  4. SparseArray为什么会有这些缺点?

通过了解这些问题,我们才能做出合理的判断,来决定是否需要继续学习,以及如何正确的使用。这篇博客,将会照着这个思路,来浅析SparryArray。【SparryArray缩写成 SA】

一,SparseArray是什么 ?

SparseArray是一个类似于HashMap的集合类,其有别于HashMap的主要有以下几点:

  1. key是基本的数据类型int。【优缺参半,限制了key的类型
  2. key,没有拆装箱操作,因为key是基本数据类型。【优点,减少内存占用
  3. key与value的映射,没有中间商赚差价。即HashMap里面,为了解决HashMap的冲突问题,额外创建的TreeNode,当出现Hash冲突时,key与value的映射,还需要走一层链表遍历查找。【优点,逻辑更简单,没有创建额外的对象(链表)
  4. 集合操作的时间更慢,因为增删查改的时间复杂度,HashMap为O(1)【最理想时为O(1),最不理想时是O(n),JDK8后改用红黑树,时间优化为O(log(n))】,而SparryArray为O(log2n)。O(log2n)标准的折半查找的时间复杂度,而其内部实现,也正是用了折半查找的算法。因此,当集合的量超过1千条时,建议还是用回HashMap。【优缺参半,实现逻辑更简单,速度更慢
  5. 数据结构不同,SparseArray,内部是两个数组,即数组+数组的形式【附图1所示】,分别用来存储key和value,它们的下标是一一对应的。而HashMap,则是数组+链表的形式【附图2所示】。【同4
  6. Android only, Java标准集合类库里面,没有这个类。其它Java项目,普遍不支持。但不排除有专门导入这个类文件的Java项目。【缺点
二,为什么选择SparseArray?

通过第一部分,我们了解到,SparseArray是一个集合类,以及它相对于HashMap的几个区别点。通过区别点,我们了解到,当你需要使用HashMap来存储,以int类型为key,且数量较少[低于1k]时,使用SparseArray来代替HashMap,可以避免HashMap的自动拆装箱操作,以及键值对的两个数组的映射关系,一一对应(下标一致),不用像HashMap一样,依赖链表来存储value,计算出key的下标后,还得再匹配一遍链表,才能获取到key对应的value。因此,我们应该只在恰当的业务需求下,使用SparseArray来代表HashMap。否则,得不偿失。

三,SparseArray的实现原理是什么?

SparseArray的内部实现原理,很简单。其内部结构是由两个数组组成,分别用来存储key和value。但是,key和value虽然分别存储在两个不同的数组里面,但他们所在的下标是一致的。 比方说,我往SparseArray, 存入一组数据:300和abc。假设,300被存到key数组的下标为8的地方。那么,abc一定是被存到value数组的下标为8的地方。这样,在查找时,只要求得key或value的下标,就可以知道另一个的下标。

那么,问题来了。这个下标是怎么得出来的?那得从put(int,T)方法讲起,也是时候,放点代码,提提神了。来人,上代码!

    
  public void put(int key, E value) {
   
   
  
        int i = ContainerHelpers.binarySearch(mKeys, mSize, key);

        if (i >= 0) {
   
   
            mValues[i] = value;
        } else {
   
   
            i = ~i;

            if (i < mSize && mValues[i] == DELETED) {
   
   
                mKeys[i] = key;
                mValues[i] = value;
               return;
            }

            if (mGarbage && mSize >= mKeys.length) {
   
   
                gc();
                // Search again because indices may have changed.
                i = ~ContainerHelpers.binarySearch(mKeys, mSize, key);
            }

            mKeys = GrowingArrayUtils.insert(mKeys
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值