在做android開發很多年的時間裏面,很多人都知道要使用 SpareArray,但是並不知道爲什麼。今天就來聊一聊SpareArray的實現源碼,講解下當前SpareArray的實現原理。
一、首先看下SpareArray的構造函數:
public SparseArray() {
this(10);
}
public SparseArray(int initialCapacity) {
if (initialCapacity == 0) {
mKeys = ContainerHelpers.EMPTY_INTS;
mValues = ContainerHelpers.EMPTY_OBJECTS;
} else {
initialCapacity = ArrayUtils.idealIntArraySize(initialCapacity);
mKeys = new int[initialCapacity];
mValues = new Object[initialCapacity];
}
mSize = 0;
}
默認是分配一個數組長度爲10,分別分配一個保存int類型的key,一個保存Object類型的值。
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);
}
if (mSize >= mKeys.length) {
int n = ArrayUtils.idealIntArraySize(mSize + 1);
int[] nkeys = new int[n];
Object[] nvalues = new Object[n];
// Log.e("SparseArray", "grow " + mKeys.length + " to " + n);
System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length);
System.arraycopy(mValues, 0, nvalues, 0, mValues.length);
mKeys = nkeys;
mValues = nvalues;
}
if (mSize - i != 0) {
// Log.e("SparseArray", "move " + (mSize - i));
System.arraycopy(mKeys, i, mKeys, i + 1, mSize - i);
System.arraycopy(mValues, i, mValues, i + 1, mSize - i);
}
mKeys[i] = key;
mValues[i] = value;
mSize++;
}
}
在上面添加數據的代碼中發現,裏面使用了一個非常重要的方法,就是二分查找法,來查找當前key的位置,然後,在適當的位置把當前值插入進去,因此,SparseArray添加的數組的內容一定是有序的。並且,它存儲的數值都是按鍵值從小到大的順序排列好的。其實append方法的實現方式和put的實現方式類似,這裏不再詳細講解。
- public E get(int key)
- public E get(int key, E valueIfKeyNotFound)
- public void delete(int key)
- public void remove(int key)
還有一個clear方法,就是全部清除當前的所有數據。
通過上面的簡單分析,基本可以知道,SparseArray使用的是純數組的方式來實現的,不管是key,還是value都是一個數組。
而HashMap使用的是散列表(數組+鏈表)的方式實現的,查詢數據的計算方式也比數組要複雜。關於HashMap的實現原理,將在下一個章節中講解。另外,SparseArray實現了Cloneable接口,還可以調用clone方法。
對比當前的性能,總結如下: