IdentityHashMap
1.内部通过数组存储键值对,相邻元素存在键值对
比如:i 位置是key,i+1位置是value
2.当hashcode相等,出现冲突的时候,通过线性探索发解决冲突问题
3.比较的是引用相等
IdentityHashMap与常用的HashMap的区别是:
前者比较key时是“引用相等”而后者是“对象相等”,即对于k1和k2,当k1==k2时,IdentityHashMap认为两个key相等,而HashMap只有在k1.equals(k2) == true 时才会认为两个key相等。
默认的加载因子为2/3,在重新哈希后,加载因子变为1/3.当哈希表中的条目数超出了加载因子与当前容量的乘积时,通过调用 reszie 方法将容量翻倍,重新进行哈希。增加桶数,重新哈希,可能相当昂贵。
继承AbstractMap
实现Map、java.io.Serializable、Cloneable
package java.util;
import java.io.*;
public class IdentityHashMap<K,V>
extends AbstractMap<K,V>
implements Map<K,V>, java.io.Serializable, Cloneable
{
/**
* 默认容量
*/
private static final int DEFAULT_CAPACITY = 32;
/**
* 最小容量
*/
private static final int MINIMUM_CAPACITY = 4;
/**
* 最大容量
*/
private static final int MAXIMUM_CAPACITY = 1 << 29;
/**
* 输出存储结构
*/
private transient Object[] table;
/**
* 键值对个数
* @serial
*/
private int size;
/**
* 修改次数
*/
private transient int modCount;
/**
* 更新容器时候的阈值= (capacity * load factor).
*/
private transient int threshold;
/**
* Value representing null keys inside tables.
*/
private static final Object NULL_KEY = new Object();
/**
* Use NULL_KEY for key if it is null.
*/
private static Object maskNull(Object key) {
return (key == null ? NULL_KEY : key);
}
/**
* Returns internal representation of null key back to caller as null.
*/
private static Object unmaskNull(Object key) {
return (key == NULL_KEY ? null : key);
}
/**
* 构造函数
*/
public IdentityHashMap() {
init(DEFAULT_CAPACITY);
}
/**
* 构造函数
*
* @param expectedMaxSize the expected maximum size of the map
* @throws IllegalArgumentException if <tt>expectedMaxSize</tt> is negative
*/
public IdentityHashMap(int expectedMaxSize) {
if (expectedMaxSize < 0)
throw new IllegalArgumentException("expectedMaxSize is negative: "
+ expectedMaxSize);
init(capacity(expectedMaxSize));
}
/**
* Returns the appropriate capacity for the specified expected maximum
* size. Returns the smallest power of two between MINIMUM_CAPACITY
* and MAXIMUM_CAPACITY, inclusive, that is greater than
* (3 * expectedMaxSize)/2, if such a number exists. Otherwise
* returns MAXIMUM_CAPACITY. If (3 * expectedMaxSize)/2 is negative, it
* is assumed that overflow has occurred, and MAXIMUM_CAPACITY is returned.
*/
private int capacity(int expectedMaxSize) {
// Compute min capacity for expectedMaxSize given a load factor of 2/3
int minCapacity = (3 * expectedMaxSize)/2;
// Compute the appropriate capacity
int result;
if (minCapacity > MAXIMUM_CAPACITY || minCapacity < 0) {
result = MAXIMUM_CAPACITY;
} else {
result = MINIMUM_CAPACITY;
while (result < minCapacity)
result <<= 1;
}
return result;
}
/**
* init
*/
private void init(int initCapacity) {
// assert (initCapacity & -initCapacity) == initCapacity; // power of 2
// assert initCapacity >= MINIMUM_CAPACITY;
// assert initCapacity <= MAXIMUM_CAPACITY;
threshold = (initCapacity * 2)/3; // 进行扩容时候的阈值
table = new Object[2 * initCapacity]; // 2倍,表示key value相邻存储
}
/**
* 构造函数,m集合元素加入到当前集合中
*/
public IdentityHashMap(Map<? extends K, ? extends V> m) {
// Allow for a bit of growth
this((int) ((1 + m.size()) * 1.1));
putAll(m);
}
/**
* size
*/
public int size() {
return size;
}
/**
* isEmpty
*/
public boolean isEmpty() {
return size == 0;
}
/**
* Returns index for Object x.
*/
private static int hash(Object x, int length) {
int h = System.identityHashCode(x);
// Multiply by -127, and left-shift to use least bit as part of hash
return ((h << 1) - (h << 8)) & (length - 1);
}
/**
*循环的方式,找到下一个key的id
*/
private static int nextKeyIndex(int i, int len) {
return (i + 2 < len ? i + 2 : 0);
}
/**
* V get(Object key)
*/
public V get(Object key) {
Object k = maskNull(key);
Object[] tab = table;
int len = tab.length;
int i = hash(k, len); // 根据hash计算应该在数组中的id
while (true) {
Object item = tab[i]; // 当前key
if (item == k) // 比较是否相等,相等下一个位置就是value
return (V) tab[i + 1];
if (item == null)
return null;
i = nextKeyIndex(i, len); // 上面不满足,根据上一个i 更新 i
}
}
/**
* containsKey 和 get 很类似
*/
public boolean containsKey(Object 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 true;
if (item == null)
return false;
i = nextKeyIndex(i, len);
}
}
/**
* containsValue
*/
public boolean containsValue(Object value) {
Object[] tab = table;
for (int i = 1</