SparseArray
在Android API里,Google提供了一种替代HashMap<Integer, E>的数据结构,这种数据结构就是SparseArray。
先来回顾下HashMap,HashMap是由 数组 + 单向链表 组成的容器,默认大小为16,每次put时算出index,然后放入数组内,这样造成的问题就是内存中数组元素不是连续的,而是散列的,因此浪费了内存。
而SparseArray就是为了解决这个问题而产生的。
先来看看SparseArray的成员变量
public class SparseArray<E> implements Cloneable {
private static final Object DELETED = new Object();
private boolean mGarbage = false;
private int[] mKeys; //存放所有的key
private Object[] mValues; //存放所有的value
private int mSize; //容器容量
在SparseArray里,有两个数组,一个数组存放key,一个存放value。
再看一下SparseArray的构造函数
public SparseArray() {
this(10); //空参构造函数,默认容量为10
}
public SparseArray(int initialCapacity) {
if (initialCapacity == 0) {
mKeys = EmptyArray.INT;
mValues = EmptyArray.OBJECT;
} else {
//生成固定大小的数组,存放value
mValues = ArrayUtils.newUnpaddedObjectArray(initialCapacity);
mKeys = new int[mValues.length]; //根据value,生成对应容量的key数组
}
mSize = 0;
}
我们看一下put方法
public void put(int key, E value) {
//通过二分查找,找到对应的index
int i = ContainerHelpers.binarySearch(mKeys, mSize, key);
if (i >= 0) {
//如果有此元素,在对应位置覆盖value
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。
gc();
// Search again because indices may have changed.
// 重新算出index
i = ~ContainerHelpers.binarySearch(mKeys, mSize, key);
}
//插入元素
mKeys = GrowingArrayUtils.insert(mKeys, mSize, i, key);
mValues = GrowingArrayUtils.insert(mValues, mSize, i, value);
mSize++;
}
}
看一下get方法
public E get(int key, E valueIfKeyNotFound) {
//二分查找index
int i = ContainerHelpers.binarySearch(mKeys, mSize, key);
//如果没有此key或者已经删除,就返回传入的valueIfKeyNotFound
if (i < 0 || mValues[i] == DELETED) {
return valueIfKeyNotFound;
} else {
//返回找到的元素
return (E) mValues[i];
}
}
看一下delete方法
public void delete(int key) {
//二分查找找到index
int i = ContainerHelpers.binarySearch(mKeys, mSize, key);
if (i >= 0) {
if (mValues[i] != DELETED) {
//标记删除元素,等待GC
mValues[i] = DELETED;
mGarbage = true;
}
}
}
总结:
SparseArray是两个数组组成的键值对容器,key的数据类型只能为int,每次都通过二分查找来寻找key。