SparseArray
SparseArray核心代码
两个构造函数默认数组容量10
public SparseArray() {
this(10);
}
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;
}
//通过 key 来返回对应的 value,前面在分析 put() 的时候已经分析过了二分查找。那么这里如果找到了,就会通过下标直接从 mValues[] 中返回。
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];
}
}
//This is Arrays.binarySearch(), but doesn't do any argument validation.
public static int binarySearch(int[] array, int size, int value) {
int lo = 0;
int hi = size - 1;
while (lo <= hi) {
// 高位+低位之各除以 2,写成右移,即通过位运算替代除法以提高运算效率
final int mid = (lo + hi) >>> 1;
final int midVal = array[mid];
if (midVal < value) {
lo = mid + 1;
} else if (midVal > value) {
hi = mid - 1;
} else {
return mid; // value found
}
}
//若没找到,则lo是value应该插入的位置,是一个正数。对这个正数去反,返回负数回去
return ~lo; // value not present
}
public void put(int key, E value) {
// 1.先进行二分查找
int i = ContainerHelpers.binarySearch(mKeys, mSize, key);
// 2. 如果找到了,则 i 必大于等于 0
if (i >= 0) {
mValues[i] = value;
} else {
// 3. 没找到,则找一个正确的位置再插入
i = ~i;
if (i < mSize && mValues[i] == DELETED) {
mKeys[i] = key;
mValues[i] = value;
return;
}
//可能value元素已经被删除了
if (mGarbage && mSize >= mKeys.length) {
gc();//执行一次压缩,此gc非jvm的gc
// 重新搜索一遍
i = ~ContainerHelpers.binarySearch(mKeys, mSize, key);
}
mKeys = GrowingArrayUtils.insert(mKeys, mSize, i, key);
mValues = GrowingArrayUtils.insert(mValues, mSize, i, value);
mSize++;
}
}
public static int[] insert(int[] array, int currentSize, int index, int element) {
//确认 当前集合长度 小于等于 array数组长度
assert currentSize <= array.length;
//不需要扩容
if (currentSize + 1 <= array.length) {
//将array数组内从 index 移到 index + 1,共移了 currentSize - index 个,即从index开始后移一位,那么就留出 index 的位置来插入新的值。
System.arraycopy(array, index, array, index + 1, currentSize - index);
//在index处插入新的值
array[index] = element;
return array;
}
//需要扩容,构建新的数组,新的数组大小由growSize() 计算得到
int[] newArray = new int[growSize(currentSize)];
//这里再分 3 阶段赋值。
//1.将原数组中 index 之前的数据复制到新数组中
System.arraycopy(array