SparseIntArray原理分析

栏目: 编程工具 · 发布时间: 6年前

内容简介:SparseSetArray目前在sdk中还处于hide状态,故在做总结的时候就不分析它了。之前已经分析过

SparseArray 优化了 intObject 键值对的存储, SparseIntArray 优化了 intint 键值对的存储。android中在键值对存储上的优化主要做了一下几种类型的优化:

  • int --> Object (SparseArray)
  • int --> int (SparseIntArray)
  • int --> boolean (SparseBooleanArray)
  • int --> long (SparseLongArray)
  • int --> Set (SparseSetArray)

SparseSetArray目前在sdk中还处于hide状态,故在做总结的时候就不分析它了。

之前已经分析过 SparseArray ,本文就分析下 SparseIntArray 的实现,并在最后总结下这几种键值对在实现上的共同点。

继承结构

SparseIntArray原理分析

以上为 SparseIntArray 的继承体系。 SparseIntArray 只实现了 Cloneable 接口,结构比较简单。其实阅读源码可以发现, SparseArraySparseIntArraySparseBooleanArraySparseLongArray 都只实现了 Cloneable 接口。

存储结构

SparseIntArray原理分析

以上为 SparseIntArray 的存储结构,mKeys存储的是int类型的键,mValues存储的是int类型的value。

查找元素

// 查找键key在mKeys的下标
    public int indexOfKey(int key) {
        return ContainerHelpers.binarySearch(mKeys, mSize, key);
    }
    
    // 查找value在mValues的下标
    public int indexOfValue(int value) {
        for (int i = 0; i < mSize; i++)
            if (mValues[i] == value)
                return i;
        return -1;
    }
复制代码

元素的查找分键查找和值查找,键查找使用二分查找,值查找直接使用循环遍历。

添加元素

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

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

            mKeys = GrowingArrayUtils.insert(mKeys, mSize, i, key);
            mValues = GrowingArrayUtils.insert(mValues, mSize, i, value);
            mSize++;
        }
    }
复制代码

添加元素首先使用二分查找找到key在mKeys数组的下标,也就是value在mValues数组的下标。如果 ContainerHelpers.binarySearch(mKeys,mSize,key) 在mKeys数组中没有找到key,则返回key待插入位置的下标的取反,如果找到了key,则直接更新mValues对应位置的值即可。 GrowingArrayUtils.insert 函数的实现如下:

public static int[] insert(int[] array, int currentSize, int index, int element) {
        assert currentSize <= array.length;
    
        if (currentSize + 1 <= array.length) {
            System.arraycopy(array, index, array, index + 1, currentSize - index);
            array[index] = element;
            return array;
        }
    
        int[] newArray = ArrayUtils.newUnpaddedIntArray(growSize(currentSize));
        System.arraycopy(array, 0, newArray, 0, index);
        newArray[index] = element;
        System.arraycopy(array, index, newArray, index + 1, array.length - index);
        return newArray;
    }
复制代码

函数的逻辑很简单,首先断言了currentSize <= array.length;如果array在不需要扩大容量的情况下可以添加一个元素,则先将待插入位置index开始的元素整体后移一位,然后插入元素,否则先扩容,然后将元素拷贝到新的数组中。

删除元素

public void delete(int key) {
        int i = ContainerHelpers.binarySearch(mKeys, mSize, key);
        if (i >= 0) {
            removeAt(i);
        }
    }
    
    public void removeAt(int index) {
        System.arraycopy(mKeys, index + 1, mKeys, index, mSize - (index + 1));
        System.arraycopy(mValues, index + 1, mValues, index, mSize - (index + 1));
        mSize--;
    }
复制代码

删除元素主要涉及以上两个方法, delete(int key) 根据 key 进行删除, removeAt(int index) 删除指定下标的元素。这两个方法都是 public ,故都可以直接使用。 delete(int key) ,先使用二分查找,找到 keymKeys 的下标,如果找到即 i >= 0 ,则直接删除 mKeysmValues 指定位置的元素。

总结

SparseBooleanArray , SparseLongArray 还没有分析,他们的实现规则是一样的,只是存储的数据类型的 mValues 数组是 booleanlong ,接下来就对 SparseIntArray , SparseBooleanArray , SparseLongArray 进行下总结。

  • 他们的设计目的是优化 intint , boolean , long 映射的存储
  • 使用 int 类型的数组 mKeys 存储映射的键,使用对应类型的数组 mValues 存储值
  • int 类型的键在存储上是有顺序的
  • 在查找值时,先使用二分查找,在 mKeys 中查找值在 mValues 中的下标,然后返回值

以上三种数据类型和 SparseArray 最大的区别在于 SparseArray 在删除元素的时候会将元素设置为 DELETED ,后续会有 gc 的过程。

相对于使用HashMap,这样的设计的优势和缺点:

优势:

  • 避免 int 类型的键自动装箱
  • 相较于 HashMap 使用 Node ,这样的设计使用更小的存储单元即可存储 keyvalue 的映射

缺点:

  • 在进行元素查找时使用二分查找,元素较多(谷歌给出的数字是大于1000)时,查找效率较低
  • 在进行元素的添加和删除时,可能会频繁进行元素的移动,运行效率可能会降低

以上所述就是小编给大家介绍的《SparseIntArray原理分析》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

树莓派学习指南

树莓派学习指南

[英]Peter Membrey、[澳]David Hows / 张志博、孙峻文 / 人民邮电出版社 / 2014-4 / 49.00元

树莓派(Raspberry Pi)是一款基于Linux系统的、只有一张信用卡大小的卡片式计算机。由于功能强大、性能出色、价格便宜等特点,树莓派得到了计算机硬件爱好者以及教育界的欢迎,风靡一时。 《树莓派学习指南(基于Linux)》是学习在树莓派上基于Linux进行开发的一本实践指南。全书共3个部分11章,第一部分是前两章,讲述如何设置和运行图形用户界面(GUI)。第二部分是第3章到第7章,讲......一起来看看 《树莓派学习指南》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具