众所周知,基础数组的处理效率要比集合的处理效率高出指数倍(内存寻址优势,指哪打哪,直截了当)
在HashMap<K, V> 中K为Integer类型时,简单考虑,使用K作为数组下标可以使用基础数组替代HashMap,但这样处理的话会有一个问题,那就是K值较大时,直接使用数组会导致极大的内存空间浪费(很多数组内容都由null填充)——由此想到“稀疏数组”
SparseArray就是针对这一场景设计的
数组中仅仅保存有内容的空间 这样一来,就既可以利用数组高效的优势,又避免了内存空间的浪费。
取android.util.SparseArray源码中的put API如下:
/**
* 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) {
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++;
}
}
可以看到,在查找是否包含时使用了BinarySearch(二分搜索),在插入时又做了一次容量、size检查,有无用内存时手动gc,此gc为private函数,只是对内存进行了整理,无效内容置为null
查看DELETED定义:
private static final Object DELETED = new Object();
在删除时,只是将有效索引的内容至为DELETED,将mGarbage至为true,在下次有增/改操作时进行统一的容量整理;个人感觉这一api逻辑是经验设计,为的是避免连续删除时的频繁容量整理;
结论:
使用HashMap<Integer, V>时,用SparseArray替代,可以极大地提高性能