SparseArray 源码解析
来源:互联网 发布:ubuntu强制关闭程序 编辑:程序博客网 时间:2024/06/11 11:54
SparseArray,即稀疏数组,作为一种数据结构,拥有比HashMap更高的执行效率(HashMap的装箱操作使其比SpaseArray慢,如果不考虑装箱拆箱,HashMap效率会比SparseArray高),且SparseArray对内存的使用比HashMap要少,在某些情况下,SparseArray是一种较优选择。SparseArray源码:
private int[] mKeys; private Object[] mValues; private int mSize; public SparseArray() { this(10); } public SparseArray(int initialCapacity){}
SparseArray维护两个数组,一个int[]保存key,Object[]保存value,key数组对应的i位置也就是对的value值在所value数据的i位置。SparseArray默认构造大小为10,也支持自定义大小的初始化。
private static final Object DELETED = new Object(); private boolean mGarbage = false; public void remove(int key) { delete(key); } public void delete(int key) { int i = ContainerHelpers.binarySearch(mKeys, mSize, key); if (i >= 0) { if (mValues[i] != DELETED) { mValues[i] = DELETED; mGarbage = true; } } }
先看的是SparseArray的delete和remove操作,在根据key移除相应value的时候,value[]数组并没有将对应的value彻底删除,而是将其引用DELETED , 表示此位置有空位,可以插入新值。 并将mGarbarge 置为true,用以提示数组存在是空间,以便之后的gc()使用。 而根据key的位置删除value,需要先定位key的位置,SparseArray的key值保证升序排序,因此定位使用二分查找
static int binarySearch(int[] array, int size, int value) { int lo = 0; int hi = size - 1; while (lo <= hi) { final int mid = (lo + hi) >>> 1; final int midVal = array[mid]; if (midVal < value) { lo = mid + 1; } else if (midVal > value) { hi = mid - 1; } else { return mid; // value found } } return ~lo; // value not present }
经典的二分查找,不多做说明
private void gc() { // Log.e("SparseArray", "gc start with " + mSize); int n = mSize; int o = 0; int[] keys = mKeys; Object[] values = mValues; for (int i = 0; i < n; i++) { Object val = values[i]; if (val != DELETED) { if (i != o) { keys[o] = keys[i]; values[o] = val; values[i] = null; } o++; } } mGarbage = false; mSize = o; // Log.e("SparseArray", "gc end with " + mSize); }
SparseArray的gc()操作,即将value数组和key数组变得紧凑
箭头为mSize的最大索引位置,在gc后将mGarbage设置为false
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++; }
put()首先使用二分查找定位i的位置,如果定位得到 i 且 i>=0 ,说明存在key值,此时直接更新此key对应的value值。 如果定位不到 i 的位置,将 i 取反, 看看 i 是否小于mSize 并且 key[i] 对应的 value[i] 对应的值已失效,如果满足条件,则更新 i 位置的 key 值和 value值 (和前面的差别为,前者相当于更新,更新了value,后者相当于重置,重置了key和value。且此处的更新key并不会破坏key[]的递增) ; 如果 mGarbage && mSize >= mKeys.length , 即存在失效值,且当前容量mSize超过了数组最大容量, 调用gc()是数组紧凑,并释放失效值, 此时需要再次定位 i , 因为数值位于数组中的位置已经改变。 之后使用 GrowingArrayUtils.insert(),将数组扩容,并将key和value插入相应位置。
public int size() { if (mGarbage) { gc(); } return mSize; }
返回当前容量,如果需要,则gc()
public int keyAt(int index) { if (mGarbage) { gc(); } return mKeys[index]; } public E valueAt(int index) { if (mGarbage) { gc(); } return (E) mValues[index]; }
根据索引值返回相应key或value,此索引前如果有需要则gc
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相差不多。
以上为全部内容,有些简陋,忘见谅(待理解更深再来改进)
此博客仅供个人笔记,如有错误之处,欢迎指出
- android sparseArray源码解析
- SparseArray源码解析
- Android SparseArray 源码解析
- SparseArray源码解析
- SparseArray 源码解析
- 面试必备:SparseArray源码解析
- SparseArray和ArrayMap相关源码解析
- android sparseArray源码解析,比较hashmap
- SparseArray解析
- SparseArray源码阅读
- Android SparseArray源码分析
- android SparseArray 源码分析
- Android源码-SparseArray
- ArrayMapy、SparseArray源码学习
- Android SparseArray源码详解
- 源码分析:SparseArray分析
- SparseArray源码分析
- SparseArray源码分析
- 使用skimage完成二值图像连通区域标记及属性提取
- idea警告:Unchecked cast: 'java.lang.Object' to 'java.util.List<java.lang.String[]>'
- 将Web项目War包部署到Tomcat服务器基本步骤
- 资源 | AI、神经网络、机器学习、深度学习以及大数据学习备忘单
- 关于OutputDebugStringW()输出调试的使用
- SparseArray 源码解析
- Percona-mysql5.6安装
- 批处理删除文件夹
- TableView Group样式中的控件
- JSON入门介绍
- 【数据挖掘】Apriori算法
- 发我我价格万恶陪我积分
- String字符串基本操作方法(草稿)
- ConcurrentHashMap原理解析