SpareArray
两个数组,一个存 key,一个存 value ,key 是一个有序数组。
private int[] mKeys;
private Object[] mValues;
public void put(int key, E value) {
//查找 key 对应的 index, 如果查找不到,则返回应该在的位置 index 取反。
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++;
}
}
ArrayMap
也是两个数组,一个存key 的 hash,一个存key 和 value,两个为一体,一个 key,一个 value,key 在偶数位,value 在奇数位。所以 存放 hash 值的数组长度是 存放 键值对的数组长度的 1/2。
public V put(K key, V value) {
final int osize = mSize;
final int hash;
int index;
if (key == null) {
hash = 0;
index = indexOfNull();
} else {
//hash 值直接就是
hash = mIdentityHashCode ? System.identityHashCode(key) : key.hashCode();
//寻找 index,这里存在 hash 冲突。具体看后面的分析。
index = indexOf(key, hash);
}
if (index >= 0) {
//找到 index ,也就是说之前存在相同的 key。
//计算 value 的位置。就是 key 的 index+1,key 的 index = index<<1。
index = (index<<1) + 1;
final V old = (V)mArray[index];
mArray[index] = value;
return old;
}
//没找到,取反,得到应该在的位置。
index = ~index;
if (osize >= mHashes.length) {
final int n = osize >= (BASE_SIZE*2) ? (osize+(osize>>1))
: (osize >= BASE_SIZE ? (BASE_SIZE*2) : BASE_SIZE);
if (DEBUG) Log.d(TAG, "put: grow from " + mHashes.length + " to " + n);
final int[] ohashes = mHashes;
final Object[] oarray = mArray;
allocArrays(n);
if (CONCURRENT_MODIFICATION_EXCEPTIONS && osize != mSize) {
throw new ConcurrentModificationException();
}
if (mHashes.length > 0) {
if (DEBUG) Log.d(TAG, "put: copy 0-" + osize + " to 0");
System.arraycopy(ohashes, 0, mHashes, 0, ohashes.length);
System.arraycopy(oarray, 0, mArray, 0, oarray.length);
}
freeArrays(ohashes, oarray, osize);
}
if (index < osize) {
if (DEBUG) Log.d(TAG, "put: move " + index + "-" + (osize-index)
+ " to " + (index+1));
System.arraycopy(mHashes, index, mHashes, index + 1, osize - index);
System.arraycopy(mArray, index << 1, mArray, (index + 1) << 1, (mSize - index) << 1);
}
if (CONCURRENT_MODIFICATION_EXCEPTIONS) {
if (osize != mSize || index >= mHashes.length) {
throw new ConcurrentModificationException();
}
}
mHashes[index] = hash;
mArray[index<<1] = key;
mArray[(index<<1)+1] = value;
mSize++;
return null;
}
indexOf(key, hash)
int indexOf(Object key, int hash) {
final int N = mSize;
// Important fast case: if nothing is in here, nothing to look for.
if (N == 0) {
return ~0;
}
int index = binarySearchHashes(mHashes, N, hash);
// If the hash code wasn't found, then we have no entry for this key.
if (index < 0) {
//没找到
return index;
}
// If the key at the returned index matches, that's what we want.
if (key.equals(mArray[index<<1])) {
//找到了 index,并且 key 相同。
return index;
}
// Search for a matching key after the index.
//找到了 index,但是 该 index 对应的 key并不是我们要存放的 key,这是存在 hash 冲突,所以先往右找是否有相同的 key。
int end;
for (end = index + 1; end < N && mHashes[end] == hash; end++) {
if (key.equals(mArray[end << 1])) return end;
}
// Search for a matching key before the index.
//右边没找到,往左边找是否有相同的 key。
for (int i = index - 1; i >= 0 && mHashes[i] == hash; i--) {
if (key.equals(mArray[i << 1])) return i;
}
// Key not found -- return negative value indicating where a
// new entry for this key should go. We use the end of the
// hash chain to reduce the number of array entries that will
// need to be copied when inserting.
return ~end;
}
从上面代码可以看出,如果存在 hash 冲突,并且之前没有存放过这个键值对,则在头部插入(因为是先往右边找,然后往左边找)。