IdentityHashMap
2018-10-14 10:49:28来源:博客园 阅读 ()
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不存在两种,结合图形在看代码就很容易理解了。
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 标签的作用:
- 一般的 continue 会退回最内层循环的开头(顶部),并继续执行。
- 带标签的 continue 会到达标签的位置,并重新进入紧接在那个标签后面的循环。
- 一般的 break 会中断并跳出当前循环。
- 带标签的 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); } }
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash