ArrayMap source code analysis

16327616-5147f21b24ab227a
ArrayMap structure

arrayMap main data is stored in two data

int[] mHashes; // 存储出的是每个key的hash值,并且在这些key的hash值在数组当中是从小到大排序的。
Object[] mArray; // 长度是mHashs的两倍,每两个元素分别是key和value,这两元素对应mHashs中的hash值。
    //如果key存在,则返回oldValue
    public V put(K key, V value) {
        //key的hash值
        final int hash;
        //下标
        int index;
        // 如果key为null,则hash值为0.
        if (key == null) {
            hash = 0;
            //寻找null的下标
            index = indexOfNull();
        } else {
            //根据mIdentityHashCode 取到 hash值
            hash = mIdentityHashCode ? System.identityHashCode(key) : key.hashCode();
            //根据hash值和key 找到合适的index
            index = indexOf(key, hash);
        }
        //如果index>=0,说明是替换(改)操作
        if (index >= 0) {
            //只需要更新value 不需要更新key。因为key已经存在
            index = (index<<1) + 1;
            //返回旧值
            final V old = (V)mArray[index];
            mArray[index] = value;
            return old;
        }
        //index<0,说明是插入操作。 对其取反,得到应该插入的下标
        index = ~index;
        //如果需要扩容
        if (mSize >= mHashes.length) {
            //如果容量大于8,则扩容一半。
            //否则容量大于4,则扩容到8.
            //否则扩容到4
            final int n = mSize >= (BASE_SIZE*2) ? (mSize+(mSize>>1))
                    : (mSize >= BASE_SIZE ? (BASE_SIZE*2) : BASE_SIZE);
            //临时数组
            final int[] ohashes = mHashes;
            final Object[] oarray = mArray;
            //分配空间完成扩容
            allocArrays(n);
            //复制临时数组中的数组进新数组
            if (mHashes.length > 0) {
                if (DEBUG) Log.d(TAG, "put: copy 0-" + mSize + " to 0");
                System.arraycopy(ohashes, 0, mHashes, 0, ohashes.length);
                System.arraycopy(oarray, 0, mArray, 0, oarray.length);
            }
            //释放临时数组空间
            freeArrays(ohashes, oarray, mSize);
        }
        //如果index在中间,则需要移动数组,腾出中间的位置
        if (index < mSize) {
            if (DEBUG) Log.d(TAG, "put: move " + index + "-" + (mSize-index)
                    + " to " + (index+1));
            System.arraycopy(mHashes, index, mHashes, index + 1, mSize - index);
            System.arraycopy(mArray, index << 1, mArray, (index + 1) << 1, (mSize - index) << 1);
        }
        //hash数组,就按照下标存哈希值
        mHashes[index] = hash;
        //array数组,根据下标,乘以2存key,乘以2+1 存value
        mArray[index<<1] = key;
        mArray[(index<<1)+1] = value;
        mSize++;//修改size
        return null;
    }
    //根据key和key的hash值,返回index
    int indexOf(Object key, int hash) {
        //N为当前集合size 
        final int N = mSize;
        //如果当前集合是空的,返回~0
        if (N == 0) {
            return ~0;
        }
        //根据hash值,通过二分查找,查找到目标index
        int index = ContainerHelpers.binarySearch(mHashes, N, hash);
        //如果index《0,说明该hash值之前没有存储过数据
        if (index < 0) {
            return index;
        }
        //如果index>=0,说明该hash值,之前存储过数据,找到对应的key,比对key是否相等。相等的话,返回index。说明要替换。
        if (key.equals(mArray[index<<1])) {
            return index;
        }
        //以下两个for循环是在出现hash冲突的情况下,找到正确的index的过程:
        //从index+1,遍历到数组末尾,找到hash值相等,且key相等的位置,返回
        int end;
        for (end = index + 1; end < N && mHashes[end] == hash; end++) {
            if (key.equals(mArray[end << 1])) return end;
        }

        //从index-1,遍历到数组头,找到hash值相等,且key相等的位置,返回
        for (int i = index - 1; i >= 0 && mHashes[i] == hash; i--) {
            if (key.equals(mArray[i << 1])) return i;
        }
        // key没有找到,返回一个负数。代表应该插入的位置
        return ~end;
    }

Expansion Optimization

freeArrays method, the incoming is oldhashes and oldarray, and new mSize. When the length is not enough, we need to scrap off the old array, using the new array, when the old data array handle (included mHashes and mArray) cache to the first two positions mArray, and other data to empty, if the length is 4, is used mBaseCache, if it is 8, is used mTwiceBaseCache.
These cache space is reserved for other ArrayMap, rather than the current ArrayMap.

Guess you like

Origin blog.csdn.net/weixin_33851604/article/details/90983822