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 冲突,并且之前没有存放过这个键值对,则在头部插入(因为是先往右边找,然后往左边找)。
