/**
* Creates a new SparseArray containing no mappings.
*/
public SparseArray() {
this(10);
}
/**
* Creates a new SparseArray containing no mappings that will not
* require any additional memory allocation to store the specified
* number of mappings. If you supply an initial capacity of 0, the
* sparse array will be initialized with a light-weight representation
* not requiring any additional array allocations.
*/
public SparseArray(int initialCapacity) {
if (initialCapacity == 0) {
mKeys = EmptyArray.INT;
mValues = EmptyArray.OBJECT;
} else {
mValues = ArrayUtils.newUnpaddedObjectArray(initialCapacity);
mKeys = new int[mValues.length];
}
mSize = 0;
}
複製程式碼
構造方法很簡單,就兩個構造方法,預設的不傳capacity引數的情況下建立的陣列長度是10。
常規操作
新增資料
/**
* Adds a mapping from the specified key to the specified value,
* replacing the previous mapping from the specified key if there
* was one.
*/publicvoidput(int key, E value){
//通過二分查詢來找到mKeys陣列中對應key的index索引。int i = ContainerHelpers.binarySearch(mKeys, mSize, key);
if (i >= 0) { //如果找到了,表示之前存過這個key,則覆蓋舊的value。
mValues[i] = value;
} else {
i = ~i;//取反,把負數變成正數。(註釋一)if (i < mSize && mValues[i] == DELETED) {//如果這個key對應的value之前被刪除了,但是還沒有被執行gc操作,目前還是DELETED狀態,那麼就複用此index。(註釋二)
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);//插入新key,如果需要擴容,就像ArrayList那樣,通過copy操作來完成。
mValues = GrowingArrayUtils.insert(mValues, mSize, i, value);//插入新value
mSize++;//表示新新增了一對key-value鍵值對。
}
}
複製程式碼
staticintbinarySearch(int[] array, int size, int value){
int lo = 0;
int hi = size - 1;
while (lo <= hi) {
finalint mid = (lo + hi) >>> 1;
finalint midVal = array[mid];
if (midVal < value) {
lo = mid + 1;
} elseif (midVal > value) {
hi = mid - 1;
} else {
return mid; // value found
}
}
return ~lo; // value not present
}
複製程式碼
/**
* Removes the mapping at the specified index.
*
* <p>For indices outside of the range <code>0...size()-1</code>,
* the behavior is undefined.</p>
* 主要index的範圍問題
*/publicvoidremoveAt(int index){
if (mValues[index] != DELETED) {
mValues[index] = DELETED;
mGarbage = true;
}
}
複製程式碼
get操作
public E get(int key){
return get(key, null);
}
/**
* Gets the Object mapped from the specified key, or the specified Object
* if no such mapping has been made.
*/@SuppressWarnings("unchecked")
public E get(int key, E valueIfKeyNotFound){
int i = ContainerHelpers.binarySearch(mKeys, mSize, key);
if (i < 0 || mValues[i] == DELETED) {
return valueIfKeyNotFound;
} else {
return (E) mValues[i];
}
}
複製程式碼
gc
privatevoidgc(){
// Log.e("SparseArray", "gc start with " + mSize);int n = mSize;
int o = 0;
int[] keys = mKeys;
Object[] values = mValues;
for (int i = 0; i < n; i++) {
Object val = values[i];
if (val != DELETED) {
if (i != o) {
keys[o] = keys[i];
values[o] = val;
values[i] = null;
}
o++;
}
}
mGarbage = false;
mSize = o;
// Log.e("SparseArray", "gc end with " + mSize);
}
複製程式碼