finalinthash(Object k){ int h = 0; if (useAltHashing) { if (k instanceof String) { //对字符串键使用备选哈希函数 return sun.misc.Hashing.stringHash32((String) k); } //随机种子,用来降低冲突发生的几率 h = hashSeed; }
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); return h ^ (h >>> 7) ^ (h >>> 4); }
voidtransfer(Entry[] newTable, boolean rehash){ int newCapacity = newTable.length; //遍历当前的table,将里面的元素添加到新的newTable中 for (Entry<K,V> e : table) { while(null != e) { Entry<K,V> next = e.next; if (rehash) { //重新计算hash值 e.hash = null == e.key ? 0 : hash(e.key); } //计算下标 int i = indexFor(e.hash, newCapacity); //插入到链表头部 e.next = newTable[i]; //存放在数组下标i中,所以扩容后链表的顺序与原来相反 newTable[i] = e; e = next; } } }
??jdk7中死循环问题
createEntry方法:
1 2 3 4 5 6
voidcreateEntry(int hash, K key, V value, int bucketIndex){ Entry<K,V> e = table[bucketIndex]; //把该节点插到链表头部 table[bucketIndex] = new Entry<>(hash, key, value, e); size++; }
get方法
1 2 3 4 5 6 7 8 9
public V get(Object key){ //如果键为null,调用getForNullKey方法 if (key == null) return getForNullKey(); //键不为null,调用getEntry方法 Entry<K,V> entry = getEntry(key);
returnnull == entry ? null : entry.getValue(); }
getForNullKey方法:
1 2 3 4 5 6 7 8
private V getForNullKey(){ //遍历第一个数组中的链表,因为putForNullKey是把NULL键存放到第一个数组中。 for (Entry<K,V> e = table[0]; e != null; e = e.next) { if (e.key == null) return e.value; } returnnull; }
getEntry方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
final Entry<K,V> getEntry(Object key){
//计算键的hash值 int hash = (key == null) ? 0 : hash(key); //遍历对应桶数组中的链表 for (Entry<K,V> e = table[indexFor(hash, table.length)]; e != null; e = e.next) { Object k; if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) return e; } returnnull; }
romove方法
1 2 3 4
public V remove(Object key){ Entry<K,V> e = removeEntryForKey(key); return (e == null ? null : e.value); }
//tableSizeFor(initialCapacity)返回大于initialCapacity的最小的二次幂数值。 staticfinalinttableSizeFor(int cap){ int n = cap - 1; n |= n >>> 1; n |= n >>> 2; n |= n >>> 4; n |= n >>> 8; n |= n >>> 16; return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1; } //说明:>>> 操作符表示无符号右移,高位取0
// 如果传入key对应的value已经存在,就返回存在的value,不进行替换。如果不存在,就添加key和value,返回null public V putIfAbsent(K key, V value){ return putVal(hash(key), key, value, true, true); }
abstractclassHashIterator{ Node<K,V> next; // next entry to return Node<K,V> current; // current entry int expectedModCount; // for fast-fail int index; // current slot
HashIterator() { expectedModCount = modCount; Node<K,V>[] t = table; current = next = null; index = 0; if (t != null && size > 0) { // advance to first entry // 寻找第一个包含链表节点引用的桶 do {} while (index < t.length && (next = t[index++]) == null); } }
publicfinalbooleanhasNext(){ return next != null; }
final Node<K,V> nextNode(){ Node<K,V>[] t; Node<K,V> e = next; if (modCount != expectedModCount) thrownew ConcurrentModificationException(); if (e == null) thrownew NoSuchElementException(); if ((next = (current = e).next) == null && (t = table) != null) { // 寻找下一个包含链表节点引用的桶 do {} while (index < t.length && (next = t[index++]) == null); } return e; } //省略部分代码 }
staticclassHashMapSpliterator<K,V> { final HashMap<K,V> map; Node<K,V> current; // current node int index; // current index, modified on advance/split int fence; // one past last index int est; // size estimate int expectedModCount; // for comodification checks
HashMapSpliterator(HashMap<K,V> m, int origin, int fence, int est, int expectedModCount) { this.map = m; this.index = origin; this.fence = fence; this.est = est; this.expectedModCount = expectedModCount; }
finalintgetFence(){ // initialize fence and size on first use int hi; if ((hi = fence) < 0) { HashMap<K,V> m = map; est = m.size; expectedModCount = m.modCount; Node<K,V>[] tab = m.table; hi = fence = (tab == null) ? 0 : tab.length; } return hi; }
publicfinallongestimateSize(){ getFence(); // force init return (long) est; } }
staticfinalclassKeySpliterator<K,V> extendsHashMapSpliterator<K,V> implementsSpliterator<K> { KeySpliterator(HashMap<K,V> m, int origin, int fence, int est, int expectedModCount) { super(m, origin, fence, est, expectedModCount); }
public KeySpliterator<K,V> trySplit(){ int hi = getFence(), lo = index, mid = (lo + hi) >>> 1; return (lo >= mid || current != null) ? null : new KeySpliterator<>(map, lo, index = mid, est >>>= 1, expectedModCount); }
publicvoidforEachRemaining(Consumer<? super K> action){ int i, hi, mc; if (action == null) thrownew NullPointerException(); HashMap<K,V> m = map; Node<K,V>[] tab = m.table; if ((hi = fence) < 0) { mc = expectedModCount = m.modCount; hi = fence = (tab == null) ? 0 : tab.length; } else mc = expectedModCount; if (tab != null && tab.length >= hi && (i = index) >= 0 && (i < (index = hi) || current != null)) { Node<K,V> p = current; current = null; do { if (p == null) p = tab[i++]; else { action.accept(p.key); p = p.next; } } while (p != null || i < hi); if (m.modCount != mc) thrownew ConcurrentModificationException(); } }
publicbooleantryAdvance(Consumer<? super K> action){ int hi; if (action == null) thrownew NullPointerException(); Node<K,V>[] tab = map.table; if (tab != null && tab.length >= (hi = getFence()) && index >= 0) { while (current != null || index < hi) { if (current == null) current = tab[index++]; else { K k = current.key; current = current.next; action.accept(k); if (map.modCount != expectedModCount) thrownew ConcurrentModificationException(); returntrue; } } } returnfalse; }
staticfinalclassValueSpliterator<K,V> extendsHashMapSpliterator<K,V> implementsSpliterator<V> { ValueSpliterator(HashMap<K,V> m, int origin, int fence, int est, int expectedModCount) { super(m, origin, fence, est, expectedModCount); }
public ValueSpliterator<K,V> trySplit(){ int hi = getFence(), lo = index, mid = (lo + hi) >>> 1; return (lo >= mid || current != null) ? null : new ValueSpliterator<>(map, lo, index = mid, est >>>= 1, expectedModCount); }
publicvoidforEachRemaining(Consumer<? super V> action){ int i, hi, mc; if (action == null) thrownew NullPointerException(); HashMap<K,V> m = map; Node<K,V>[] tab = m.table; if ((hi = fence) < 0) { mc = expectedModCount = m.modCount; hi = fence = (tab == null) ? 0 : tab.length; } else mc = expectedModCount; if (tab != null && tab.length >= hi && (i = index) >= 0 && (i < (index = hi) || current != null)) { Node<K,V> p = current; current = null; do { if (p == null) p = tab[i++]; else { action.accept(p.value); p = p.next; } } while (p != null || i < hi); if (m.modCount != mc) thrownew ConcurrentModificationException(); } }
publicbooleantryAdvance(Consumer<? super V> action){ int hi; if (action == null) thrownew NullPointerException(); Node<K,V>[] tab = map.table; if (tab != null && tab.length >= (hi = getFence()) && index >= 0) { while (current != null || index < hi) { if (current == null) current = tab[index++]; else { V v = current.value; current = current.next; action.accept(v); if (map.modCount != expectedModCount) thrownew ConcurrentModificationException(); returntrue; } } } returnfalse; }
staticfinalclassEntrySpliterator<K,V> extendsHashMapSpliterator<K,V> implementsSpliterator<Map.Entry<K,V>> { EntrySpliterator(HashMap<K,V> m, int origin, int fence, int est, int expectedModCount) { super(m, origin, fence, est, expectedModCount); }
public EntrySpliterator<K,V> trySplit(){ int hi = getFence(), lo = index, mid = (lo + hi) >>> 1; return (lo >= mid || current != null) ? null : new EntrySpliterator<>(map, lo, index = mid, est >>>= 1, expectedModCount); }
publicvoidforEachRemaining(Consumer<? super Map.Entry<K,V>> action){ int i, hi, mc; if (action == null) thrownew NullPointerException(); HashMap<K,V> m = map; Node<K,V>[] tab = m.table; if ((hi = fence) < 0) { mc = expectedModCount = m.modCount; hi = fence = (tab == null) ? 0 : tab.length; } else mc = expectedModCount; if (tab != null && tab.length >= hi && (i = index) >= 0 && (i < (index = hi) || current != null)) { Node<K,V> p = current; current = null; do { if (p == null) p = tab[i++]; else { action.accept(p); p = p.next; } } while (p != null || i < hi); if (m.modCount != mc) thrownew ConcurrentModificationException(); } }
publicbooleantryAdvance(Consumer<? super Map.Entry<K,V>> action){ int hi; if (action == null) thrownew NullPointerException(); Node<K,V>[] tab = map.table; if (tab != null && tab.length >= (hi = getFence()) && index >= 0) { while (current != null || index < hi) { if (current == null) current = tab[index++]; else { Node<K,V> e = current; current = current.next; action.accept(e); if (map.modCount != expectedModCount) thrownew ConcurrentModificationException(); returntrue; } } } returnfalse; }
public V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction){ if (value == null) thrownew NullPointerException(); if (remappingFunction == null) thrownew NullPointerException(); int hash = hash(key); Node<K,V>[] tab; Node<K,V> first; int n, i; int binCount = 0; TreeNode<K,V> t = null; Node<K,V> old = null; if (size > threshold || (tab = table) == null || (n = tab.length) == 0) n = (tab = resize()).length; if ((first = tab[i = (n - 1) & hash]) != null) { if (first instanceof TreeNode) old = (t = (TreeNode<K,V>)first).getTreeNode(hash, key); else { Node<K,V> e = first; K k; do { if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) { old = e; break; } ++binCount; } while ((e = e.next) != null); } } if (old != null) { V v; if (old.value != null) //根据oldValue和value参数计算value值 v = remappingFunction.apply(old.value, value); else //oldValue为null,直接取value参数 v = value; if (v != null) { old.value = v; afterNodeAccess(old); } else //计算出来的value值为null,删除节点 removeNode(hash, key, null, false, true); return v; } if (value != null) { if (t != null) t.putTreeVal(this, tab, hash, key, value); else { tab[i] = newNode(hash, key, value, first); if (binCount >= TREEIFY_THRESHOLD - 1) treeifyBin(tab, hash); } ++modCount; ++size; afterNodeInsertion(true); } return value; }
forEach
调用此方法时实现BiConsumer接口重写void accept(Object o, Object o2)方法,其中o为key,o2为value,可根据自己的实现对map中所有数据进行处理。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
@Override publicvoidforEach(BiConsumer<? super K, ? super V> action){ Node<K,V>[] tab; if (action == null) thrownew NullPointerException(); if (size > 0 && (tab = table) != null) { int mc = modCount; for (int i = 0; i < tab.length; ++i) { for (Node<K,V> e = tab[i]; e != null; e = e.next) action.accept(e.key, e.value); } if (modCount != mc) thrownew ConcurrentModificationException(); } }
ConcurrentModificationException异常
错误实例
1 2 3 4 5 6 7 8 9 10 11 12
publicstaticvoidmain(String[] args){ HashMap<String, String> hashMap = new HashMap<>(); hashMap.put("1", "Hello"); hashMap.put("2", "World"); Iterator<String> it = hashMap.keySet().iterator(); while (it.hasNext()) { String key = it.next(); if (key.equals("1")) { it.remove(); } } }
报错
1 2 3 4 5
//报错 Exception in thread "main" java.util.ConcurrentModificationException at java.util.HashMap$HashIterator.nextNode(HashMap.java:1437) at java.util.HashMap$KeyIterator.next(HashMap.java:1461) at com.yufh.Exception.main(Exception.java:21)
HashMap.java:1437:
1 2 3
if (modCount != expectedModCount) thrownew ConcurrentModificationException(); //如果HashMap中modCount和expectedModCount不相等,则会抛出异常
HashIterator() { expectedModCount = modCount; Node<K,V>[] t = table; current = next = null; index = 0; if (t != null && size > 0) { // advance to first entry do {} while (index < t.length && (next = t[index++]) == null); } }