基本结构 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 static final int DEFAULT_INITIAL_CAPACITY = 1 << 4 ; static final int MAXIMUM_CAPACITY = 1 << 30 ;static final float DEFAULT_LOAD_FACTOR = 0.75f ;static final int TREEIFY_THRESHOLD = 8 ;static final int UNTREEIFY_THRESHOLD = 6 ;static final int MIN_TREEIFY_CAPACITY = 64 ;static class Node <K ,V > implements Map .Entry <K ,V > { final int hash; final K key; V value; Node<K,V> next; ... } static final class TreeNode <K ,V > extends LinkedHashMap .Entry <K ,V > { TreeNode<K,V> parent; TreeNode<K,V> left; TreeNode<K,V> right; TreeNode<K,V> prev; boolean red; ...
通用方法 hash(Object key) - 计算 hashcode 将 key 计算出来的 hashcode 和他的高位进行异或运算,这一步是一个散列运算,目的是为了减少哈希冲突,具体参考–>为什么 HashMap 的 hash 值要右移 16 位?
1 2 3 4 static final int hash (Object key) { int h; return (key == null ) ? 0 : (h = key.hashCode()) ^ (h >>> 16 ); }
comparableClassFor(Object x) - 判断 x 是否实现 Compareble 接口 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 static Class<?> comparableClassFor(Object x) { if (x instanceof Comparable) { Class<?> c; Type[] ts, as; Type t; ParameterizedType p; if ((c = x.getClass()) == String.class) return c; if ((ts = c.getGenericInterfaces()) != null ) { for (int i = 0 ; i < ts.length; ++i) { if (((t = ts[i]) instanceof ParameterizedType) && ((p = (ParameterizedType)t).getRawType() == Comparable.class) && (as = p.getActualTypeArguments()) != null && as.length == 1 && as[0 ] == c) return c; } } } return null ; }
compareComparables(Class<?> kc, Object k, Object x) - 获取 compareTo()比较结果 1 2 3 4 static int compareComparables (Class<?> kc, Object k, Object x) { return (x == null || x.getClass() != kc ? 0 : ((Comparable)k).compareTo(x)); }
tableSizeFor(int cap) - 将传入容量扩展为大于该数的 2 的幂(已经是 2 的幂返回原值) 1 2 3 4 5 6 7 8 9 static final int tableSizeFor (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 的位开始,把后面的所有位都设置成 1。
构造方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 public HashMap (int initialCapacity, float loadFactor) { if (initialCapacity < 0 ) throw new IllegalArgumentException("Illegal initial capacity: " + initialCapacity); if (initialCapacity > MAXIMUM_CAPACITY) initialCapacity = MAXIMUM_CAPACITY; if (loadFactor <= 0 || Float.isNaN(loadFactor)) throw new IllegalArgumentException("Illegal load factor: " + loadFactor); this .loadFactor = loadFactor; this .threshold = tableSizeFor(initialCapacity); } public HashMap (int initialCapacity) { this (initialCapacity, DEFAULT_LOAD_FACTOR); } public HashMap () { this .loadFactor = DEFAULT_LOAD_FACTOR; }
总结一下这三个构造方法就是:传入容量就将 threshold 设为传入容量处理后的结果否则不设置。传入负载因子就将负载因子设置为传入值否则使用默认负载因子。留一个问题?这三个构造方法都没有设置容量,到底在哪里设置的呢?
get(Object key) - get 方法 1 2 3 4 5 6 public V get (Object key) { Node<K,V> e; return (e = getNode(hash(key), key)) == null ? null : e.value; }
getNode(int hash, Object key) - 获取节点 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 final Node<K,V> getNode (int hash, Object key) { Node<K,V>[] tab; Node<K,V> first, e; int n; K k; if ((tab = table) != null && (n = tab.length) > 0 && (first = tab[(n - 1 ) & hash]) != null ) { if (first.hash == hash && ((k = first.key) == key || (key != null && key.equals(k)))) return first; if ((e = first.next) != null ) { if (first instanceof TreeNode) return ((TreeNode<K,V>)first).getTreeNode(hash, key); do { if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) return e; } while ((e = e.next) != null ); } } return null ; }
getTreeNode(int h, Object k) - 获取树节点 1 2 3 4 5 final TreeNode<K,V> getTreeNode (int h, Object k) { return ((parent != null ) ? root() : this ).find(h, k, null ); }
find(int h, Object k, Class<?> kc) - 红黑树中查找 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 final TreeNode<K,V> find (int h, Object k, Class<?> kc) { TreeNode<K,V> p = this ; do { int ph, dir; K pk; TreeNode<K,V> pl = p.left, pr = p.right, q; if ((ph = p.hash) > h) p = pl; else if (ph < h) p = pr; else if ((pk = p.key) == k || (k != null && k.equals(pk))) return p; else if (pl == null ) p = pr; else if (pr == null ) p = pl; else if ((kc != null || (kc = comparableClassFor(k)) != null ) && (dir = compareComparables(kc, k, pk)) != 0 ) p = (dir < 0 ) ? pl : pr; else if ((q = pr.find(h, k, kc)) != null ) return q; else p = pl; } while (p != null ); return null ; }
put(K key, V value) - 插入节点
1 2 3 4 public V put (K key, V value) { return putVal(hash(key), key, value, false , true ); }
putVal(int hash, K key, V value, boolean onlyIfAbsent,boolean evict) - 插入节点 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 final V putVal (int hash, K key, V value, boolean onlyIfAbsent, boolean evict) { Node<K,V>[] tab; Node<K,V> p; int n, i; if ((tab = table) == null || (n = tab.length) == 0 ) n = (tab = resize()).length; if ((p = tab[i = (n - 1 ) & hash]) == null ) tab[i] = newNode(hash, key, value, null ); else { Node<K,V> e; K k; if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k)))) e = p; else if (p instanceof TreeNode) e = ((TreeNode<K,V>)p).putTreeVal(this , tab, hash, key, value); else { for (int binCount = 0 ; ; ++binCount) { if ((e = p.next) == null ) { p.next = newNode(hash, key, value, null ); if (binCount >= TREEIFY_THRESHOLD - 1 ) treeifyBin(tab, hash); break ; } if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) break ; p = e; } } if (e != null ) { V oldValue = e.value; if (!onlyIfAbsent || oldValue == null ) e.value = value; afterNodeAccess(e); return oldValue; } } ++modCount; if (++size > threshold) resize(); afterNodeInsertion(evict); return null ; }
putTreeVal(HashMap<K,V> map, Node<K,V>[] tab,int h, K k, V v) - 红黑树插入节点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 final TreeNode<K,V> putTreeVal (HashMap<K,V> map, Node<K,V>[] tab, int h, K k, V v) { Class<?> kc = null ; boolean searched = false ; TreeNode<K,V> root = (parent != null ) ? root() : this ; for (TreeNode<K,V> p = root;;) { int dir, ph; K pk; if ((ph = p.hash) > h) dir = -1 ; else if (ph < h) dir = 1 ; else if ((pk = p.key) == k || (k != null && k.equals(pk))) return p; else if ((kc == null && (kc = comparableClassFor(k)) == null ) || (dir = compareComparables(kc, k, pk)) == 0 ) { if (!searched) { TreeNode<K,V> q, ch; searched = true ; if (((ch = p.left) != null && (q = ch.find(h, k, kc)) != null ) || ((ch = p.right) != null && (q = ch.find(h, k, kc)) != null )) return q; } dir = tieBreakOrder(k, pk); } TreeNode<K,V> xp = p; if ((p = (dir <= 0 ) ? p.left : p.right) == null ) { Node<K,V> xpn = xp.next; TreeNode<K,V> x = map.newTreeNode(h, k, v, xpn); if (dir <= 0 ) xp.left = x; else xp.right = x; xp.next = x; x.parent = x.prev = xp; if (xpn != null ) ((TreeNode<K,V>)xpn).prev = x; moveRootToFront(tab, balanceInsertion(root, x)); return null ; } } }
balanceInsertion(TreeNode<K,V> root,TreeNode<K,V> x) - 红黑树插入平衡
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 static <K,V> TreeNode<K,V> balanceInsertion (TreeNode<K,V> root, TreeNode<K,V> x) { x.red = true ; for (TreeNode<K,V> xp, xpp, xppl, xppr;;) { if ((xp = x.parent) == null ) { x.red = false ; return x; } else if (!xp.red || (xpp = xp.parent) == null ) return root; if (xp == (xppl = xpp.left)) { if ((xppr = xpp.right) != null && xppr.red) { xppr.red = false ; xp.red = false ; xpp.red = true ; x = xpp; } else { if (x == xp.right) { root = rotateLeft(root, x = xp); xpp = (xp = x.parent) == null ? null : xp.parent; } if (xp != null ) { xp.red = false ; if (xpp != null ) { xpp.red = true ; root = rotateRight(root, xpp); } } } } else { if (xppl != null && xppl.red) { xppl.red = false ; xp.red = false ; xpp.red = true ; x = xpp; } else { if (x == xp.left) { root = rotateRight(root, x = xp); xpp = (xp = x.parent) == null ? null : xp.parent; } if (xp != null ) { xp.red = false ; if (xpp != null ) { xpp.red = true ; root = rotateLeft(root, xpp); } } } } } }
rotateLLeft(TreeNode<K,V> root,TreeNode<K,V> p) - 左旋 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 static <K,V> TreeNode<K,V> rotateLeft (TreeNode<K,V> root, TreeNode<K,V> p) { TreeNode<K,V> r, pp, rl; if (p != null && (r = p.right) != null ) { if ((rl = p.right = r.left) != null ) rl.parent = p; if ((pp = r.parent = p.parent) == null ) (root = r).red = false ; else if (pp.left == p) pp.left = r; else pp.right = r; r.left = p; p.parent = r; } return root; }
rotateRight(TreeNode<K,V> root,TreeNode<K,V> p) - 右旋 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 static <K,V> TreeNode<K,V> rotateRight (TreeNode<K,V> root, TreeNode<K,V> p) { TreeNode<K,V> l, pp, lr; if (p != null && (l = p.left) != null ) { if ((lr = p.left = l.right) != null ) lr.parent = p; if ((pp = l.parent = p.parent) == null ) (root = l).red = false ; else if (pp.right == p) pp.right = l; else pp.left = l; l.right = p; p.parent = l; } return root; }
treeifyBin(Node<K,V>[] tab, int hash) - 转换为双向链表 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 final void treeifyBin (Node<K,V>[] tab, int hash) { int n, index; Node<K,V> e; if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY) resize(); else if ((e = tab[index = (n - 1 ) & hash]) != null ) { TreeNode<K,V> hd = null , tl = null ; do { TreeNode<K,V> p = replacementTreeNode(e, null ); if (tl == null ) hd = p; else { p.prev = tl; tl.next = p; } tl = p; } while ((e = e.next) != null ); if ((tab[index] = hd) != null ) hd.treeify(tab); } }
treeify(Node<K,V>[] tab) - 转为红黑树 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 final void treeify (Node<K,V>[] tab) { TreeNode<K,V> root = null ; for (TreeNode<K,V> x = this , next; x != null ; x = next) { next = (TreeNode<K,V>)x.next; x.left = x.right = null ; if (root == null ) { x.parent = null ; x.red = false ; root = x; } else { K k = x.key; int h = x.hash; Class<?> kc = null ; for (TreeNode<K,V> p = root;;) { int dir, ph; K pk = p.key; if ((ph = p.hash) > h) dir = -1 ; else if (ph < h) dir = 1 ; else if ((kc == null && (kc = comparableClassFor(k)) == null ) || (dir = compareComparables(kc, k, pk)) == 0 ) dir = tieBreakOrder(k, pk); TreeNode<K,V> xp = p; if ((p = (dir <= 0 ) ? p.left : p.right) == null ) { x.parent = xp; if (dir <= 0 ) xp.left = x; else xp.right = x; root = balanceInsertion(root, x); break ; } } } } moveRootToFront(tab, root); }
remove(Object key) - 删除 1 2 3 4 5 6 public V remove (Object key) { Node<K,V> e; return (e = removeNode(hash(key), key, null , false , true )) == null ? null : e.value; }
removeNode(int hash, Object key, Object value,boolean matchValue, boolean movable) - 删除节点 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 final Node<K,V> removeNode (int hash, Object key, Object value, boolean matchValue, boolean movable) { Node<K,V>[] tab; Node<K,V> p; int n, index; if ((tab = table) != null && (n = tab.length) > 0 && (p = tab[index = (n - 1 ) & hash]) != null ) { Node<K,V> node = null , e; K k; V v; if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k)))) node = p; else if ((e = p.next) != null ) { if (p instanceof TreeNode) node = ((TreeNode<K,V>)p).getTreeNode(hash, key); else { do { if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) { node = e; break ; } p = e; } while ((e = e.next) != null ); } } if (node != null && (!matchValue || (v = node.value) == value || (value != null && value.equals(v)))) { if (node instanceof TreeNode) ((TreeNode<K,V>)node).removeTreeNode(this , tab, movable); else if (node == p) tab[index] = node.next; else p.next = node.next; ++modCount; --size; afterNodeRemoval(node); return node; } } return null ; }
removeTreeNode(HashMap<K,V> map, Node<K,V>[] tab,boolean movable) - 删除树节点 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 final void removeTreeNode (HashMap<K,V> map, Node<K,V>[] tab, boolean movable) { int n; if (tab == null || (n = tab.length) == 0 ) return ; int index = (n - 1 ) & hash; TreeNode<K,V> first = (TreeNode<K,V>)tab[index], root = first, rl; TreeNode<K,V> succ = (TreeNode<K,V>)next, pred = prev; if (pred == null ) tab[index] = first = succ; else pred.next = succ; if (succ != null ) succ.prev = pred; if (first == null ) return ; if (root.parent != null ) root = root.root(); if (root == null || (movable && (root.right == null || (rl = root.left) == null || rl.left == null ))) { tab[index] = first.untreeify(map); return ; }h TreeNode<K,V> p = this , pl = left, pr = right, replacement; if (pl != null && pr != null ) { TreeNode<K,V> s = pr, sl; while ((sl = s.left) != null ) s = sl; boolean c = s.red; s.red = p.red; p.red = c; TreeNode<K,V> sr = s.right; TreeNode<K,V> pp = p.parent; if (s == pr) { p.parent = s; s.right = p; } else { TreeNode<K,V> sp = s.parent; if ((p.parent = sp) != null ) { if (s == sp.left) sp.left = p; else sp.right = p; } if ((s.right = pr) != null ) pr.parent = s; } p.left = null ; if ((p.right = sr) != null ) sr.parent = p; if ((s.left = pl) != null ) pl.parent = s; if ((s.parent = pp) == null ) root = s; else if (p == pp.left) pp.left = s; else pp.right = s; if (sr != null ) replacement = sr; else replacement = p; } else if (pl != null ) replacement = pl; else if (pr != null ) replacement = pr; else replacement = p; if (replacement != p) { TreeNode<K,V> pp = replacement.parent = p.parent; if (pp == null ) root = replacement; else if (p == pp.left) pp.left = replacement; else pp.right = replacement; p.left = p.right = p.parent = null ; } TreeNode<K,V> r = p.red ? root : balanceDeletion(root, replacement); if (replacement == p) { TreeNode<K,V> pp = p.parent; p.parent = null ; if (pp != null ) { if (p == pp.left) pp.left = null ; else if (p == pp.right) pp.right = null ; } } if (movable) moveRootToFront(tab, r); }
balanceDeletion(TreeNode<K,V> root,TreeNode<K,V> x) - 删除平衡 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 static <K,V> TreeNode<K,V> balanceDeletion (TreeNode<K,V> root, TreeNode<K,V> x) { for (TreeNode<K,V> xp, xpl, xpr;;) { if (x == null || x == root) return root; else if ((xp = x.parent) == null ) { x.red = false ; return x; } else if (x.red) { x.red = false ; return root; } else if ((xpl = xp.left) == x) { if ((xpr = xp.right) != null && xpr.red) { xpr.red = false ; xp.red = true ; root = rotateLeft(root, xp); xpr = (xp = x.parent) == null ? null : xp.right; } if (xpr == null ) x = xp; else { TreeNode<K,V> sl = xpr.left, sr = xpr.right; if ((sr == null || !sr.red) && (sl == null || !sl.red)) { xpr.red = true ; x = xp; } else { if (sr == null || !sr.red) { if (sl != null ) sl.red = false ; xpr.red = true ; root = rotateRight(root, xpr); xpr = (xp = x.parent) == null ? null : xp.right; } if (xpr != null ) { xpr.red = (xp == null ) ? false : xp.red; if ((sr = xpr.right) != null ) sr.red = false ; } if (xp != null ) { xp.red = false ; root = rotateLeft(root, xp); } x = root; } } } else { if (xpl != null && xpl.red) { xpl.red = false ; xp.red = true ; root = rotateRight(root, xp); xpl = (xp = x.parent) == null ? null : xp.left; } if (xpl == null ) x = xp; else { TreeNode<K,V> sl = xpl.left, sr = xpl.right; if ((sl == null || !sl.red) && (sr == null || !sr.red)) { xpl.red = true ; x = xp; } else { if (sl == null || !sl.red) { if (sr != null ) sr.red = false ; xpl.red = true ; root = rotateLeft(root, xpl); xpl = (xp = x.parent) == null ? null : xp.left; } if (xpl != null ) { xpl.red = (xp == null ) ? false : xp.red; if ((sl = xpl.left) != null ) sl.red = false ; } if (xp != null ) { xp.red = false ; root = rotateRight(root, xp); } x = root; } } } } }
resize() - 扩容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 final Node<K,V>[] resize() { Node<K,V>[] oldTab = table; int oldCap = (oldTab == null ) ? 0 : oldTab.length; int oldThr = threshold; int newCap, newThr = 0 ; if (oldCap > 0 ) { if (oldCap >= MAXIMUM_CAPACITY) { threshold = Integer.MAX_VALUE; return oldTab; } else if ((newCap = oldCap << 1 ) < MAXIMUM_CAPACITY && oldCap >= DEFAULT_INITIAL_CAPACITY) newThr = oldThr << 1 ; } else if (oldThr > 0 ) newCap = oldThr; else { newCap = DEFAULT_INITIAL_CAPACITY; newThr = (int )(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY); } if (newThr == 0 ) { float ft = (float )newCap * loadFactor; newThr = (newCap < MAXIMUM_CAPACITY && ft < (float )MAXIMUM_CAPACITY ? (int )ft : Integer.MAX_VALUE); } threshold = newThr; @SuppressWarnings({"rawtypes","unchecked"}) Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap]; table = newTab; if (oldTab != null ) { for (int j = 0 ; j < oldCap; ++j) { Node<K,V> e; if ((e = oldTab[j]) != null ) { oldTab[j] = null ; if (e.next == null ) newTab[e.hash & (newCap - 1 )] = e; else if (e instanceof TreeNode) ((TreeNode<K,V>)e).split(this , newTab, j, oldCap); else { Node<K,V> loHead = null , loTail = null ; Node<K,V> hiHead = null , hiTail = null ; Node<K,V> next; do { next = e.next; if ((e.hash & oldCap) == 0 ) { if (loTail == null ) loHead = e; else loTail.next = e; loTail = e; } else { if (hiTail == null ) hiHead = e; else hiTail.next = e; hiTail = e; } } while ((e = next) != null ); if (loTail != null ) { loTail.next = null ; newTab[j] = loHead; } if (hiTail != null ) { hiTail.next = null ; newTab[j + oldCap] = hiHead; } } } } } return newTab; }
关于 (e.hash & oldCap) == 0 j 以及 j+oldCap
本部分来自深入理解 HashMap(四): 关键源码逐行分析之 resize 扩容
明确三个前提条件:
oldCap 为 2 的幂,假设为2^n
newCal 为oldCap*2
,即2^(n+1)
HashMap 确定下标位置是对 hashcode 按容量取余,即(n-1) & hash
;
例如:
假设 oldCap 为 16,即 2^4,(16-1)的二进制结果为0000 0000 0000 1111
,所以(16-1)&hash
就是对 hash 取后四位。 而扩容后 newCap 为 32,即 2^4,(16-1)的二进制结果为0000 0000 0001 1111
,而(32-1)&hash
就是对 hash 取后五位。
根据上面的计算结果,假设 hash 后四位为 abcd,扩容后的下标不是0abcd
就是1abcd
。其中0abcd
就是原位置。而1abcd
如下:
1 1abcd = 0abcd + 10000 = oabcd + oldCap。
故虽然数组大小扩大了一倍,但是同一个 key 在新旧 table 中对应的 index 却存在一定联系:要么一致,要么相差一个 oldCap。
而新旧 index 是否一致就体现在 hash 值的第 4 位(我们把最低为称作第 0 位), 怎么拿到这一位的值呢, 只要:
1 hash & 0000 0000 0000 0000 0000 0000 0001 0000
也就是e.hash & oldCap
.
故得出结论:
如果 (e.hash & oldCap) == 0 则该节点在新表的下标位置与旧表一致都为 j 如果 (e.hash & oldCap) == 1 则该节点在新表的下标位置 j + oldCap
根据这个条件, 我们将原位置的链表拆分成两个链表, 然后一次性将整个链表放到新的 Table 对应的位置上.
split(HashMap<K,V> map, Node<K,V>[] tab, int index, int bit) - 拆分红黑树
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 final void split (HashMap<K,V> map, Node<K,V>[] tab, int index, int bit) { TreeNode<K,V> b = this ; TreeNode<K,V> loHead = null , loTail = null ; TreeNode<K,V> hiHead = null , hiTail = null ; int lc = 0 , hc = 0 ; for (TreeNode<K,V> e = b, next; e != null ; e = next) { next = (TreeNode<K,V>)e.next; e.next = null ; if ((e.hash & bit) == 0 ) { if ((e.prev = loTail) == null ) loHead = e; else loTail.next = e; loTail = e; ++lc; } else { if ((e.prev = hiTail) == null ) hiHead = e; else hiTail.next = e; hiTail = e; ++hc; } } if (loHead != null ) { if (lc <= UNTREEIFY_THRESHOLD) tab[index] = loHead.untreeify(map); else { tab[index] = loHead; if (hiHead != null ) loHead.treeify(tab); } } if (hiHead != null ) { if (hc <= UNTREEIFY_THRESHOLD) tab[index + bit] = hiHead.untreeify(map); else { tab[index + bit] = hiHead; if (loHead != null ) hiHead.treeify(tab); } } }
总结 花了 n 天时间,不知不觉就把 HashMap 源码看了大半,开始以为 get(),put(),remove()三个方法的工作量不会太多,后面发现总和起来基本就是一个完整的 HashMap 了。从中也看到一些很精妙的设计,为了减少哈希冲突,加快查询效率。有很多技巧都值得学习啊。