IdentityHashMap 为什么用 == 而不是 equals?内部长什么样?什么时候该用?这篇一项项量出来(HashMap 的树化、扩容在已有文章里)。
两个内容相同但不是同一个对象的 String(k1.equals(k2) = true,k1 == k2 = false):HashMap.size() = 1,IdentityHashMap.size() = 2
id.get(k1) = 1,id.get(k2) = 2,id.get(new String("key")) = null(换一个新对象就找不到)
两个字面量 "key" 是同一个对象(intern):IdentityHashMap.size() = 1
装箱的 Integer:put(100) 两次 + put(1000) 两次,size = 3(100 在 Integer 缓存里是同一个对象,1000 每次装箱都是新对象)
null 键:id.put(null, 9) 可以,id.get(null) = 9元素个数增长时 table 数组长度的变化: 第 1 个元素时 table.length=64; 第 22 个元素时 table.length=128; 第 43 个元素时 table.length=256; 第 86 个元素时 table.length=512; table 是一个 Object[]:键和值交替放在相邻的槽里(长度 = 2 × 容量),没有 Node 对象;100 个元素时 table.length = 512 只放一个键 "K" → 12345:键在 table[48](偶数下标),table[49] = 12345(紧挨着的下一个槽就是值);table 里非空元素的类型 = [Integer, String](只有键和值本身,没有 Entry/Node 对象) new IdentityHashMap(100) 的 table.length = 512
键是含 100 个元素的 List(hashCode 与 equals 都要遍历 100 个元素):200000 次 put + 200000 次 get:HashMap 91 ms,IdentityHashMap 32 ms(2.8 倍)
图里有两个 name 相同(equals 为 true)但不是同一个的节点 a1、a2,以及 b:按身份记录访问过的节点集合大小 = 3,而用 HashSet(按 equals)是 2(a1 和 a2 被当成同一个)