眾所周知,基礎數組的處理效率要比集合的處理效率高出指數倍(內存尋址優勢,指哪打哪,直截了當)
在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替代,可以極大地提高性能