/** * This method is invoked whenever the value in an entry is * overwritten by an invocation of put(k,v) for a key k that's already * in the HashMap. */ void recordAccess(HashMap<K,V> m) { }
/** * This method is invoked whenever the entry is * removed from the table. */ void recordRemoval(HashMap<K,V> m) { } }
/** * A randomizing value associated with this instance that is applied to * hash code of keys to make hash collisions harder to find. If 0 then * alternative hashing is disabled. */ // 用于减少key的hash code冲突 // 如果是0,表示不使用替代的hash算法 transientint hashSeed = 0;
// disable alternative hashing if -1 if (threshold == -1) { threshold = Integer.MAX_VALUE; }
if (threshold < 0) { thrownew IllegalArgumentException("value must be positive integer."); } } catch(IllegalArgumentException failed) { thrownew Error("Illegal value for 'jdk.map.althashing.threshold'", failed); }
/** * This method is invoked whenever the value in an entry is * overwritten by an invocation of put(k,v) for a key k that's already * in the HashMap. */ void recordAccess(HashMap<K,V> m) { }
/** * This method is invoked whenever the entry is * removed from the table. */ void recordRemoval(HashMap<K,V> m) { } }
privateabstractclassHashIterator<E>implementsIterator<E> { Entry<K,V> next; // next entry to return int expectedModCount; // For fast-fail int index; // current slot Entry<K,V> current; // current entry
HashIterator() { expectedModCount = modCount; if (size > 0) { // 设置next为第一个entry Entry[] t = table; while (index < t.length && (next = t[index++]) == null) ; } }
public final boolean hasNext() { return next != null; }
finalEntry<K,V> nextEntry() { if (modCount != expectedModCount) thrownewConcurrentModificationException(); Entry<K,V> e = next; if (e == null) thrownewNoSuchElementException();
if ((next = e.next) == null) { Entry[] t = table; while (index < t.length && (next = t[index++]) == null) ; } current = e; return e; }
public void remove() { if (current == null) thrownewIllegalStateException(); if (modCount != expectedModCount) thrownewConcurrentModificationException(); Object k = current.key; current = null; HashMap.this.removeEntryForKey(k); expectedModCount = modCount; } }
privatefinalclassValueIteratorextendsHashIterator<V> { public V next() { return nextEntry().value; } }
privatefinalclassKeyIteratorextendsHashIterator<K> { public K next() { return nextEntry().getKey(); } }
privatefinalclassEntryIteratorextendsHashIterator<Map.Entry<K,V>> { public Map.Entry<K,V> next() { return nextEntry(); } }
/** * Removes all of the mappings from this map. * The map will be empty after this call returns. */ publicvoidclear() { modCount++; Arrays.fill(table, null); size = 0; }
public boolean containsValue(Object value){ if (value == null) return containsNullValue();
Entry[] tab = table; for (int i = 0; i < tab.length ; i++) for (Entry e = tab[i] ; e != null ; e = e.next) if (value.equals(e.value)) returntrue; returnfalse; }
public V put(K key, V value) { if (table == EMPTY_TABLE) { inflateTable(threshold); } if (key == null) return putForNullKey(value); int hash = hash(key); int i = indexFor(hash, table.length); for (Entry<K,V> e = table[i]; e != null; e = e.next) { Object k; if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { // 注意判断条件 V oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; } }
/* * Expand the map if the map if the number of mappings to be added * is greater than or equal to threshold. This is conservative; the * obvious condition is (m.size() + size) >= threshold, but this * condition could result in a map with twice the appropriate capacity, * if the keys to be added overlap with the keys already in this map. * By using the conservative calculation, we subject ourself * to at most one extra resize. */ if (numKeysToBeAdded > threshold) { int targetCapacity = (int)(numKeysToBeAdded / loadFactor + 1); if (targetCapacity > MAXIMUM_CAPACITY) targetCapacity = MAXIMUM_CAPACITY; int newCapacity = table.length; while (newCapacity < targetCapacity) newCapacity <<= 1; if (newCapacity > table.length) resize(newCapacity); }
for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) put(e.getKey(), e.getValue()); }
内部方法
roundUpToPowerOf2
给定一个非负整数,给出大于等于这个数的2的指数幂
1 2 3 4 5 6
private static int roundUpToPowerOf2(intnumber) { // assert number >= 0 : "number must be non-negative"; returnnumber >= MAXIMUM_CAPACITY ? MAXIMUM_CAPACITY : (number > 1) ? Integer.highestOneBit((number - 1) << 1) : 1; }
inflateTable
扩容,容量是2的指数幂。扩容后,设置下一次需要扩容的阈值。
1 2 3 4 5 6 7 8
privatevoidinflateTable(int toSize){ // Find a power of 2 >= toSize int capacity = roundUpToPowerOf2(toSize); //设置阈值:当size达到这个值时,再次扩容 threshold = (int) Math.min(capacity * loadFactor, MAXIMUM_CAPACITY + 1); table = new Entry[capacity]; initHashSeedAsNeeded(capacity); }
private boolean containsNullValue() { Entry[] tab = table; for (int i = 0; i < tab.length ; i++) for (Entry e = tab[i] ; e != null ; e = e.next) if (e.value == null) return true; return false; }
private V getForNullKey(){ if (size == 0) { returnnull; } for (Entry<K,V> e = table[0]; e != null; e = e.next) { if (e.key == null) return e.value; } returnnull; }
final int hash(Object k) { int h = hashSeed; if (0 != h && k instanceof String) { return sun.misc.Hashing.stringHash32((String) k); }
h ^= k.hashCode();
// This function ensures that hashCodes that differ only by // constant multiples at each bit position have a bounded // number of collisions (approximately 8 at default load factor). h ^= (h >>> 20) ^ (h >>> 12); returnh ^ (h >>> 7) ^ (h >>> 4); }
Table Of Contents
Overview
Qiyang Zuo
Write something about Java Web development distributed computing technologies.