- SparseArray用于映射integers到object。但不像普通数组那样,sparseArray的元素间没有无用元素。 在映射integers到object的过程中,SparseArray由于采用避免自动装箱的keys和它的数据结构不依赖额外的对象来存储映射关系的实现,因此它比hashMap的内存使用更高效一些。
- SparseArray在查找keys的过程中采用了二分查找, 这种实现不适合数据量大的情况。由于查找时要用到二分查找,添加删除时涉及到数组其他元素的挪动,
- 因此通常SparseArray会比hashMap慢。当处理上百的数据量,这种性能差异不是特别明显,性能差异不超过50%。
- 为了优化性能,SparseArray针对remove case作了优化,remove时它不是立即挤压数组空间,而是标记为delete。 这个被标记的元素要么被重复利用,要
- 么在多次remove之后通过一次gc操作中被挤压出去。gc需要在下列情况之前被执行:数组要扩容;get map size;get values;
- 核心的put代码如下:
-
-
-
- /**
- * Adds a mapping from the specified key to the specified value,
- * replacing the previous mapping from the specified key if there
- * was one.
- */
- public void put(int key, E value) {
- //先二分查找,确定插入位置,保证了key数组的有序性
- int i = ContainerHelpers.binarySearch(mKeys, mSize, key);
- if (i >= 0) {
- //找到了,直接替换
- mValues[i] = value;
- } else {
- //一点小技巧,跟二分查找的返回值有关
- //没找到的情况下i的意义是 i = -insertPoint -1,比如i=-2,则insertPoint=1
- //而-2在内存中存的是补码,对他取反刚好得insertPoint,跟上面计算结果一样,但位操作更高效
- i = ~i;
- //若i在size范围内,且刚好对应位置标记为delete了,直接放入
- if (i < mSize && mValues[i] == DELETED) {
- mKeys[i] = key;
- mValues[i] = value;
- return;
- }
- //若前面if不成立,即i超出了size范围,或者对应的位置的元素是有效的
- 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++;
- }
- }
- }
-
SparseArray详解
最新推荐文章于 2023-02-06 18:45:48 发布