除了我们常用JDK提供的容器以外,Android还提供的自己的容器类,如SparseArray就是其中比较常见的一个类。

特点

  1. SparseArray是一个整形到对象的映射;
  2. 在整形到对象的映射这方面,它比HashMap在内存上更有效率;

    因为它避免了自动装箱的key,它的数据结构不依赖一个额外的Entry对象

  3. 它把映射关系存储在两个数组中,用二分查找算法查找元素;

    这种实现不宜用在含有大量数据项的数据结构中,当数据量为1K以下的时候,性能差异不是那么明显,保持在50%以下。

  4. 对于已知的性能问题,这个容器进行了优化:在remove的时候并不立即执行变更,而是将元素标记为删除,让在适合的时机进行重用,或者在gc(容器内的gc方法)的时候进行全部移除。这个gc操作,会在容器容量增加的时候执行。

只看这些特点也没啥用,顺便分析一下源码,加深下印象吧:

    private int[] mKeys;    private Object[] mValues;    private int mSize;

看一下这三个重要的属性,用于存储key值的整形数组,用于存储value的对象数组,和数组的大小。

再来看看构造函数:

 public SparseArray() {        this(10);    }public SparseArray(int initialCapacity) {        if (initialCapacity == 0) {            mKeys = EmptyArray.INT;            mValues = EmptyArray.OBJECT;        } else {            mValues = ArrayUtils.newUnpaddedObjectArray(initialCapacity);            mKeys = new int[mValues.length];        }        mSize = 0;    }

一个无参构造函数,会初始化一个初始大小为10的容量,一个是有参构造函数,如果传入初始容量为0,则创建两个空数组,否则创建指定大小。这里的容量指的是数组的大小,但是这个容器的大小依然是0.

看一看存取操作吧:

public E get(int key) {        return get(key, null);    }public E get(int key, E valueIfKeyNotFound) {        int i = ContainerHelpers.binarySearch(mKeys, mSize, key);        if (i < 0 || mValues[i] == DELETED) {            return valueIfKeyNotFound;        } else {            return (E) mValues[i];        }    }

可以看到,取得操作是先经过二分查找到对应的位置,然后取值,没什么好说的,存的操作也是一样。

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, mSize, i, key);            mValues = GrowingArrayUtils.insert(mValues, mSize, i, value);            mSize++;        }    }public void append(int key, E value) {        if (mSize != 0 && key <= mKeys[mSize - 1]) {            put(key, value);            return;        }        if (mGarbage && mSize >= mKeys.length) {            gc();        }        mKeys = GrowingArrayUtils.append(mKeys, mSize, key);        mValues = GrowingArrayUtils.append(mValues, mSize, value);        mSize++;    }

其中put添加键值对,如果已经存在,则进行替换;
append优化了key比原来map中所有的key都要大的情况。

更多相关文章

  1. Android版本兼容器
  2. Android(安卓)内存缓存框架 LruCache 的源码分析
  3. 怎么把数组从android客户端传递到php服务器
  4. Android(安卓)jni编程浅入深出之-- 与原生代码通信
  5. Android(安卓)自定义 View 之 onMeasure() 源码分析及重写
  6. Android(安卓)Drawable之Bitmap
  7. Android(安卓)深入研究JNI
  8. Android(安卓)BitmapFactory图片压缩处理(大位图二次采样压缩处理
  9. Android(安卓)1.6 支持更多的屏幕大小和分辨率

随机推荐

  1. Annotation Processor在Android下的应用
  2. Android网络编程之——Android登录系统模
  3. Android媒体扫描代码分析
  4. 什么是Anddroid ANR
  5. [置顶] 定义一个ImageVIew出现警告的去除
  6. 用SQLiteOpenHelper实现操作SQLite
  7. AdapterViewFlipper实现翻滚广告效果
  8. andorid跳过系统API获取以太网IP,网关,DNS,M
  9. 引入第三方库ic_launcher冲突
  10. Android热修复原理(一)热修复框架对比和代