IdentityHashMap数据结构

Posted june777

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了IdentityHashMap数据结构相关的知识,希望对你有一定的参考价值。

也是比较古老的类了,看了下源码,该类结构的简单记录。
IdentityHashMap是保存到一个Object[]数组里,不一样的是比如key的索引为0,那么value保留紧跟着的位置上,而且相同索引会顺序往下排,循环时索引的自增是+2。具体看源码

    public V put(K key, V value) {
        final Object k = maskNull(key);

        retryAfterResize: for (;;) {
            final Object[] tab = table;
            final int len = tab.length;
            //索引
            int i = hash(k, len);
            找到相同的值,注意判断的地方是==,而不是equals。
            for (Object item; (item = tab[i]) != null;
                 i = nextKeyIndex(i, len)) {
                if (item == k) {
                    @SuppressWarnings("unchecked")
                        V oldValue = (V) tab[i + 1];
                    tab[i + 1] = value;
                    return oldValue;
                }
            }
            //没有找到相同的值,要把新值加到数组中
            //先把长度+1
            final int s = size + 1;
            // Use optimized form of 3 * s.
            // Next capacity is len, 2 * current capacity.
            //3s 如果大于长度,就扩容,成功的话就继续循环,直到3s <= len了 或者扩容失败
            if (s + (s << 1) > len && resize(len))
                continue retryAfterResize;
            //操作数+1
            modCount++;
            //新的i位置放key
            tab[i] = k;
            //i+1 放value
            tab[i + 1] = value;
            size = s;
            return null;
        }
    }

    private static int nextKeyIndex(int i, int len) {
        //索引+2
        return (i + 2 < len ? i + 2 : 0);
    }

    private boolean resize(int newCapacity) {
        // assert (newCapacity & -newCapacity) == newCapacity; // power of 2
        //扩成2倍
        int newLength = newCapacity * 2;

        Object[] oldTable = table;
        int oldLength = oldTable.length;
        if (oldLength == 2 * MAXIMUM_CAPACITY) { // can't expand any further
            if (size == MAXIMUM_CAPACITY - 1)
                throw new IllegalStateException("Capacity exhausted.");
            return false;
        }
        if (oldLength >= newLength)
            return false;
        //创建新数组
        Object[] newTable = new Object[newLength];
        //旧数组开始复制,下表子增量为2
        for (int j = 0; j < oldLength; j += 2) {
            Object key = oldTable[j];
            if (key != null) {
                Object value = oldTable[j+1];
                //清空原数组的key和value
                oldTable[j] = null;
                oldTable[j+1] = null;
                //计算新数组下表
                int i = hash(key, newLength);
                //找到可以放值的索引
                while (newTable[i] != null)
                    i = nextKeyIndex(i, newLength);
                //放key
                newTable[i] = key;
                //放value
                newTable[i + 1] = value;
            }
        }
        table = newTable;
        return true;
    }

以上是关于IdentityHashMap数据结构的主要内容,如果未能解决你的问题,请参考以下文章

java中key值可以重复的map:IdentityHashMap

允许Key重复的Map - IdentityHashMap

容器--IdentityHashMap

为什么IdentityHashMap使用线性探测来解决冲突

java:Map借口及其子类HashMap五,identityHashMap子类

java.util.IdentityHashMap#hash(Object x, int length)为什么总是返回2的倍数?