当前位置: 移动技术网 > IT编程>开发语言>Java > IdentityHashMap

IdentityHashMap

2018年10月14日  | 移动技术网IT编程  | 我要评论

applicationshutdownhooks中使用到了identityhashmap,查看其api解释为

this class implements the map interface with a hash table, using reference-equality in place of object-equality when comparing keys (and values). in other words, in an identityhashmap, two keys k1 and k2 are considered equal if and only if (k1==k2). (in normal map implementations (like hashmap) two keys k1 and k2 are considered equal if and only if (k1==null ? k2==null : k1.equals(k2)).)

大致意思为identityhashmap中key是否相等的规则判断是根据key的引用是否相等来判断,而不像正常的hashmap是通过key的值是否相等来判断。

equals方法

identityhashmap中的equals方法是首先对比两个map的引用是否相等,如果不相等,再去循环所有的值判断是否相等,判断值是否相等时,使用的判断公式为 == 

public boolean equals(object o) {
        // 引用相等直接返回true
        if (o == this) {
            return true;
        } else if (o instanceof identityhashmap) {
            // 长度或内容有一个不相等时,返回false,否则返回true
            identityhashmap<?,?> m = (identityhashmap<?,?>) o;
            if (m.size() != size)
                return false;

            object[] tab = m.table;
            for (int i = 0; i < tab.length; i+=2) {
                object k = tab[i];
                // contanismapping方法为判断当前map的key为k的值是否等于传入map的key为k的值
                if (k != null && !containsmapping(k, tab[i + 1]))
                    return false;
            }
            return true;
        } else if (o instanceof map) {
            map<?,?> m = (map<?,?>)o;
            return entryset().equals(m.entryset());
        } else {
            return false;  // o is not a map
        }
    }

private boolean containsmapping(object key, object value) {
        object k = masknull(key);
        object[] tab = table;
        int len = tab.length;
        int i = hash(k, len);
        while (true) {
            object item = tab[i];
            if (item == k)
            //  判断是否相等时使用==,为判断两个对象的引用是否相等
                return tab[i + 1] == value;
            if (item == null)
            // 未找到该key,返回false
                return false;
            i = nextkeyindex(i, len);
        }
    }

 

 

put方法

put方法是如何操作底层数组的,下图给予了说明,分为key存在和key不存在两种,结合图形在看代码就很容易理解了。

put方法说明

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);
            // 如果key存在,就将新的value给之前value所在的位置
            // key如果在table[i] value就在table[i+1],所以nextkeyindex的作用就是i+2
            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;
                }
            }

            final int s = size + 1;
            // use optimized form of 3 * s.
            // next capacity is len, 2 * current capacity.
            // table空间不足时的扩容

            if (s + (s << 1) > len && resize(len))
                continue retryafterresize;
            // 如果key不存在时的赋值
            modcount++;
            tab[i] = k;
            tab[i + 1] = value;
            size = s;
            return null;
        }
    }

 

在put方法段中有段代码为: retryafterresize: for (;;) { ,然后下面接着有一段代码为continue retryafterresize;  这是java标签的用法(但此处我不知道为什么要用java标签,直接continue不就行了)

java 标签的作用:

  1. 一般的 continue 会退回最内层循环的开头(顶部),并继续执行。
  2. 带标签的 continue 会到达标签的位置,并重新进入紧接在那个标签后面的循环。
  3. 一般的 break 会中断并跳出当前循环。
  4. 带标签的 break 会中断并跳出标签所指的循环。

标签测试:

public class test {

    public static void main(string[] args) throws interruptedexception {
        label: for (int j = 0; j < 2; j++) {
            for (int i = 1; i < 10; i++) {
                thread.sleep(1000);
                if (i % 3 == 0) {
                    system.out.println(i);
                    continue label;
                }
                system.out.println(j + " run");
            }
        }
    }
}
------------------
输出结果:

0 run

0 run

3

1 run

1 run

3

 

get方法

public v get(object key) {
        object k = masknull(key);
        object[] tab = table;
        int len = tab.length;
        int i = hash(k, len);
     // 死循环遍历table数组
        while (true) {
            object item = tab[i];
       // 如果命中相同的key,就返回table[i+1]的值
            if (item == k)
                return (v) tab[i + 1];
       // 如果遍历完数组还未命中,就返回空
            if (item == null)
                return null;
            i = nextkeyindex(i, len);
        }
    }

 

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网