IdentityHashMap继承了AbstractMap,实现了Map, java.io.Serializable, Cloneable接口。
IdentityHashMap是一个比较奇葩的hashMap,为什么这么说呢,因为它和别的HashMap有很大区别。
和其它HashMap相比,IdentityHashMap并没有使用hash桶链表等结构存储内部数据,而是只使用了数组来存储数据。
transient Object[] table; //存储数据的数组
put(K key, V value)
public V put(K key, V value) {
//允许key=null,但是会包装成对象
final Object k = maskNull(key);
retryAfterResize: for (;;) {
final Object[] tab = table;
final int len = tab.length;
int i = hash(k, len);
for (Object item; (item = tab[i]) != null;
i = nextKeyIndex(i, len)) {
//identityHashMap比较的是两个key对象是否想等(k1 == k2),而不是k1.equals(k2),只用两个对象想等时,才是把旧对象key所对应的value覆盖
if (item == k) {
@SuppressWarnings("unchecked")
V oldValue = (V) tab[i + 1];
tab[i + 1] = value;
return oldValue;
}
}
final int s = size + 1;
//当数组容量>当前数组容量的1/3会对数组可扩容
if (s + (s << 1) > len && resize(len))
continue retryAfterResize;
//另一点特殊的地方就是:
//IdentityHashMap的key位置会在数组的偶数上,value在key+1的位置上
modCount++;
tab[i] = k;
tab[i + 1] = value;
size = s;
return null;
}
}
get(Object key)
public V get(Object key) {
//对key=null的key进行包装
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 (V) tab[i + 1];
if (item == null)
return null;
//返回当前key位置的下一个key,即k+2,如果大于数组的长度返回0
i = nextKeyIndex(i, len);
}
}
总结
- IdentityHashMap内部使用数组存储数据(伪hash表),2key位置存储key,2key+1存储value。
- IdentityHashMap允许key=null,但是会把key=null包装成对象。
- IdentityHashMap判断key是否相等使用的是“对象相等”,即key1==key2。
IdentityHashMap内部无序。
JDK版本1.8.0_92。