一 特性
- 键之间的比较不是食用equals 而是使用==也就是比较内存地址
- 可以使用这个存储代理对象
- 支持null值的key和value
- 是非线程安全的,可以借助Collections.synchronizedMap 来获得线程安全的实例
-
二 属性
/*** The initial capacity used by the no-args constructor.* MUST be a power of two. The value 32 corresponds to the* (specified) expected maximum size of 21, given a load factor* of 2/3. 无参数构造函数使用这个默认值初始化*/private static final int DEFAULT_CAPACITY = 32;/*** The minimum capacity, used if a lower value is implicitly specified* by either of the constructors with arguments. The value 4 corresponds* to an expected maximum size of 2, given a load factor of 2/3.* MUST be a power of two. 最小的容量*/private static final int MINIMUM_CAPACITY = 4;/*** The maximum capacity, used if a higher value is implicitly specified* by either of the constructors with arguments.* MUST be a power of two <= 1<<29.** In fact, the map can hold no more than MAXIMUM_CAPACITY-1 items* because it has to have at least one slot with the key == null* in order to avoid infinite loops in get(), put(), remove()*/private static final int MAXIMUM_CAPACITY = 1 << 29;/*** The table, resized as necessary. Length MUST always be a power of two.*/transient Object[] table; // non-private to simplify nested class access/*** The number of key-value mappings contained in this identity hash map.** @serial*/int size;/*** The number of modifications, to support fast-fail iterators*/transient int modCount;/*** Value representing null keys inside tables.*/static final Object NULL_KEY = new Object();
三 重要方法
hash
- 计算hash值的方法 ((h << 1) - (h << 8)) & (length - 1)
- nextKeyIndex
- 计算给定位置的hash冲突的解决为止,采用开放寻址方式解决hash冲突
resize
扩容方法 扩容的大小是原来大小的两倍,会创建一个新的数组并将每个元素重进进行hash
四 添加
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);//这里的循环的为开放寻址法的地址 i = nextKeyIndex(i, len) 来控制的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.//判断当前已经存在的元素的 2.5倍是否大于数组的长度 扩容后重新retryAfterResizeif (s + (s << 1) > len && resize(len))continue retryAfterResize;modCount++;tab[i] = k;tab[i + 1] = value;size = s;return null;}}
五 删除
public V remove(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) {modCount++;size--;@SuppressWarnings("unchecked")V oldValue = (V) tab[i + 1];tab[i + 1] = null;tab[i] = null;closeDeletion(i);return oldValue;}if (item == null)return null;i = nextKeyIndex(i, len);}}
六 获取
public V get(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 (V) tab[i + 1];if (item == null)return null;//如果都不等于则代表发生了hash冲突,使用开放寻址方式找下一个位置i = nextKeyIndex(i, len);}}
七 resize
private boolean resize(int newCapacity) {// assert (newCapacity & -newCapacity) == newCapacity; // power of 2 新大小是原来的两倍int newLength = newCapacity * 2;Object[] oldTable = table;int oldLength = oldTable.length;if (oldLength == 2 * MAXIMUM_CAPACITY) { // can't expand any furtherif (size == MAXIMUM_CAPACITY - 1)throw new IllegalStateException("Capacity exhausted.");return false;}if (oldLength >= newLength)return false;Object[] newTable = new Object[newLength];//重新进行更新hash槽位的过程for (int j = 0; j < oldLength; j += 2) {Object key = oldTable[j];if (key != null) {Object value = oldTable[j+1];oldTable[j] = null;oldTable[j+1] = null;int i = hash(key, newLength);while (newTable[i] != null)i = nextKeyIndex(i, newLength);newTable[i] = key;newTable[i + 1] = value;}}table = newTable;return true;}
