源码分析之Map(三)HashMap
HashMap基于哈希表的Map接口实现,是以key-value存储形式存在(除了不同步和允许使用 null 之外,HashMap 类与 Hashtable 大致相同)。HashMap 的实现不是同步的,这意味着它不是线程安全的。它的key、value都可以为null。此外,HashMap中的映射不是有序的。
数据结构
在 JDK1.8 中,HashMap 是由 数组+链表+红黑树构成,新增了红黑树作为底层数据结构,结构变得复杂了,但是效率也变的更高效。数组保存着每个链表的表头结点;查找时,先通过hash函数计算key的hash值,再根据key的hash值计算数组索引(取余法),然后根据索引找到链表表头结点,然后遍历查找该链表;
HashMap源码解析
1 public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable { 2 3 private static final long serialVersionUID = 362498820763181265L; 4 5 /** 6 * The default initial capacity. MUST be a power of two.初始化大小16 7 */ 8 static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16 9 10 /** 11 * The maximum capacity. MUST be a power of two <= 1<<30.最大值,小于Integer最大值 12 */ 13 static final int MAXIMUM_CAPACITY = 1 << 30; 14 15 /** 16 * The load factor used when none specified in constructor.默认负载因子 17 */ 18 static final float DEFAULT_LOAD_FACTOR = 0.75f; 19 20 /** 21 * The bin count threshold for using a tree rather than list for a bin. 链表长度到8,转为红黑树 22 */ 23 static final int TREEIFY_THRESHOLD = 8; 24 25 /** 26 * The bin count threshold for untreeifying a (split) bin during a 27 * resize operation. 树大小为6,转为链表 28 */ 29 static final int UNTREEIFY_THRESHOLD = 6; 30 31 /** 32 * The smallest table capacity for which bins may be treeified. 33 * Should be at least 4 * TREEIFY_THRESHOLD Map里面的数量至少到 64,表中的桶才能转为树。(当哈希冲突超过8,但是元素数量小于64时,会优先扩容而不是树化) 34 */ 35 static final int MIN_TREEIFY_CAPACITY = 64; 36 37 /** 38 * Basic hash bin node, used for most entries. (See below for TreeNode subclass, and in LinkedHashMap for its Entry subclass.) 39 */ 40 static class Node<K,V> implements Map.Entry<K,V> { 41 final int hash; 42 final K key; 43 V value; 44 Node<K,V> next; 45 46 Node(int hash, K key, V value, Node<K,V> next) { 47 this.hash = hash; 48 this.key = key; 49 this.value = value; 50 this.next = next; 51 } 52 53 public final K getKey() { return key; } 54 public final V getValue() { return value; } 55 public final String toString() { return key + "=" + value; } 56 57 public final int hashCode() { //节点的hashcode由key的hashcode与value的hashcode异或(按位相同为0,不相同为1)得到 58 return Objects.hashCode(key) ^ Objects.hashCode(value); 59 } 60 61 public final V setValue(V newValue) { 62 V oldValue = value; 63 value = newValue; 64 return oldValue; 65 } 66 67 public final boolean equals(Object o) { 68 if (o == this) 69 return true; 70 if (o instanceof Map.Entry) { 71 Map.Entry<?,?> e = (Map.Entry<?,?>)o; 72 if (Objects.equals(key, e.getKey()) && Objects.equals(value, e.getValue())) 73 return true; 74 } 75 return false; 76 } 77 } 78 79 /* ---------------- Static utilities -------------- */ 80 81 /** 82 * 获取hash值方法,右移16位 异或,减少hash冲突 83 */ 84 static final int hash(Object key) { 85 int h; 86 return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); 87 } 88 89 /** 90 * Returns x's Class if it is of the form "class C implements 91 * Comparable<C>", else null. 如果key实现了Comparable就返回具体类型,否则返回null 92 */ 93 static Class<?> comparableClassFor(Object x) { 94 if (x instanceof Comparable) { 95 Class<?> c; Type[] ts, as; Type t; ParameterizedType p; 96 if ((c = x.getClass()) == String.class) // bypass checks 97 return c; 98 if ((ts = c.getGenericInterfaces()) != null) { 99 for (int i = 0; i < ts.length; ++i) { 100 if (((t = ts[i]) instanceof ParameterizedType) && 101 ((p = (ParameterizedType)t).getRawType() == 102 Comparable.class) && 103 (as = p.getActualTypeArguments()) != null && 104 as.length == 1 && as[0] == c) // type arg is c 105 return c; 106 } 107 } 108 } 109 return null; 110 } 111 112 /** 113 * Returns k.compareTo(x) if x matches kc (k's screened comparable 114 * class), else 0. 比较传入的key和当前遍历元素的key 115 */ 116 @SuppressWarnings({"rawtypes","unchecked"}) // for cast to Comparable 117 static int compareComparables(Class<?> kc, Object k, Object x) { 118 return (x == null || x.getClass() != kc ? 0 : 119 ((Comparable)k).compareTo(x)); 120 } 121 122 /** 123 * Returns a power of two size for the given target capacity. 找到大于或等于cap的最小2的幂 124 */ 125 static final int tableSizeFor(int cap) { 126 int n = cap - 1; 127 n |= n >>> 1; 128 n |= n >>> 2; 129 n |= n >>> 4; 130 n |= n >>> 8; 131 n |= n >>> 16; 132 return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1; 133 } 134 135 /* ---------------- Fields -------------- */ 136 137 /** 138 * The table, initialized on first use, and resized as necessary. When allocated, length is always a power of two. * 存放元素的地方,连续的内存空间,由数组来实现,但存放的元素并不要求紧凑存储。hash索引映射到数组中即为数组索引 139 */ 140 transient Node<K,V>[] table; 141 142 /** 143 * Holds cached entrySet(). Note that AbstractMap fields are used for keySet() and values(). 144 */ 145 transient Set<Map.Entry<K,V>> entrySet; 146 147 /** 148 * The number of key-value mappings contained in this map. map中k-v的实时数量 149 */ 150 transient int size; 151 152 /** 153 * The number of times this HashMap has been structurally modified 154 */ 155 transient int modCount; 156 157 /** 158 * The next size value at which to resize (capacity * load factor). 159 * 下一次扩容的预判值。map中元素数量超过这个值就扩容,扩容后HashMap容量是之前的两倍 160 */ 161 int threshold; 162 163 /** 164 * The load factor for the hash table. 加载因子,用来衡量hashMap满的程度。 165 * @serial 166 */ 167 final float loadFactor; 168 169 /* ---------------- Public operations -------------- */ 170 171 /** 172 * Constructs an empty <tt>HashMap</tt> with the specified initial capacity and load factor. 173 * 174 * @param initialCapacity the initial capacity 175 * @param loadFactor the load factor 176 * @throws IllegalArgumentException if the initial capacity is negative or the load factor is nonpositive 177 */ 178 public HashMap(int initialCapacity, float loadFactor) { 179 if (initialCapacity < 0) 180 throw new IllegalArgumentException("Illegal initial capacity: " + initialCapacity); 181 if (initialCapacity > MAXIMUM_CAPACITY) 182 initialCapacity = MAXIMUM_CAPACITY; 183 if (loadFactor <= 0 || Float.isNaN(loadFactor)) 184 throw new IllegalArgumentException("Illegal load factor: " + loadFactor); 185 this.loadFactor = loadFactor; 186 this.threshold = tableSizeFor(initialCapacity); 187 } 188 189 /** 190 * Constructs an empty <tt>HashMap</tt> with the specified initial capacity and the default load factor (0.75).*/ 191 public HashMap(int initialCapacity) { 192 this(initialCapacity, DEFAULT_LOAD_FACTOR); 193 } 194 195 /** 196 * Constructs an empty <tt>HashMap</tt> with the default initial capacity (16) and the default load factor (0.75). 197 */ 198 public HashMap() { 199 this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted 200 } 201 202 /** 203 * Constructs a new <tt>HashMap</tt> with the same mappings as the specified <tt>Map</tt>. 204 * @param m the map whose mappings are to be placed in this map 205 * @throws NullPointerException if the specified map is null 206 */ 207 public HashMap(Map<? extends K, ? extends V> m) { 208 this.loadFactor = DEFAULT_LOAD_FACTOR; 209 putMapEntries(m, false); 210 } 211 212 /** 213 * Implements Map.putAll and Map constructor 214 * @param m the map 215 * @param evict false when initially constructing this map, else true (relayed to method afterNodeInsertion). 216 */ 217 final void putMapEntries(Map<? extends K, ? extends V> m, boolean evict) { 218 int s = m.size(); 219 if (s > 0) { 220 if (table == null) { // pre-size 221 float ft = ((float)s / loadFactor) + 1.0F; 222 int t = ((ft < (float)MAXIMUM_CAPACITY) ? (int)ft : MAXIMUM_CAPACITY); 223 if (t > threshold) 224 threshold = tableSizeFor(t); 225 } 226 else if (s > threshold) 227 resize(); 228 for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) { 229 K key = e.getKey(); 230 V value = e.getValue(); 231 putVal(hash(key), key, value, false, evict); 232 } 233 } 234 } 235 236 /** 237 * Returns the number of key-value mappings in this map.*/ 238 public int size() { 239 return size; 240 } 241 242 /** 243 * Returns <tt>true</tt> if this map contains no key-value mappings. 244 */ 245 public boolean isEmpty() { 246 return size == 0; 247 } 248 249 /** 250 * Returns the value to which the specified key is mapped,or {@code null} if this map contains no mapping for the key.*/ 251 public V get(Object key) { 252 Node<K,V> e; 253 return (e = getNode(hash(key), key)) == null ? null : e.value; 254 } 255 256 /** 257 * Implements Map.get and related methods 258 * @param hash hash for key 259 * @param key the key 260 * @return the node, or null if none 261 */ 262 final Node<K,V> getNode(int hash, Object key) { 263 Node<K,V>[] tab; Node<K,V> first, e; int n; K k; 264 if ((tab = table) != null && (n = tab.length) > 0 && (first = tab[(n - 1) & hash]) != null) { // (n-1)&hash 根据hash和map大小确定下标位置 265 if (first.hash == hash && // always check first node 266 ((k = first.key) == key || (key != null && key.equals(k)))) 267 return first; 268 if ((e = first.next) != null) { 269 if (first instanceof TreeNode) //如果first是TreeNode类型,调用红黑树方法查询 270 return ((TreeNode<K,V>)first).getTreeNode(hash, key); 271 do { //对链表进行查找 272 if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) 273 return e; 274 } while ((e = e.next) != null); 275 } 276 } 277 return null; 278 } 279 280 /** 281 * Returns <tt>true</tt> if this map contains a mapping for the specified key.*/ 282 public boolean containsKey(Object key) { 283 return getNode(hash(key), key) != null; 284 } 285 286 /** 287 * Associates the specified value with the specified key in this map. 288 * If the map previously contained a mapping for the key, the old value is replaced.*/ 289 public V put(K key, V value) { 290 return putVal(hash(key), key, value, false, true); 291 } 292 293 /** 294 * Implements Map.put and related methods 295 * 296 * @param hash hash for key 297 * @param key the key 298 * @param value the value to put 299 * @param onlyIfAbsent if true, don't change existing value 300 * @param evict if false, the table is in creation mode. 301 * @return previous value, or null if none 302 */ 303 final V putVal(int hash, K key, V value, boolean onlyIfAbsent,boolean evict) { 304 Node<K,V>[] tab; Node<K,V> p; int n, i; 305 if ((tab = table) == null || (n = tab.length) == 0) //空表,需要初始化 306 n = (tab = resize()).length; 307 if ((p = tab[i = (n - 1) & hash]) == null) //根据hash确定节点所在桶的位置,并且判断桶中该位置没有元素 308 tab[i] = newNode(hash, key, value, null); 309 else { 310 Node<K,V> e; K k; 311 if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k)))) //当前位置就是元素p,说明目的是修改值 312 e = p; 313 else if (p instanceof TreeNode) //红黑树处理方法 314 e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value); 315 else { 316 for (int binCount = 0; ; ++binCount) { //链表结构 317 if ((e = p.next) == null) { //如果当前节点是尾节点 318 p.next = newNode(hash, key, value, null); 319 if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st 320 treeifyBin(tab, hash); //链表较长,树化 321 break; 322 } 323 if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) //如果元素不匹配 324 break; 325 p = e; 326 } 327 } 328 if (e != null) { // existing mapping for key 找到匹配元素 329 V oldValue = e.value; 330 if (!onlyIfAbsent || oldValue == null) 331 e.value = value; 332 afterNodeAccess(e); 333 return oldValue; 334 } 335 } 336 ++modCount; 337 if (++size > threshold) //没有找到匹配元素,判断增加元素后是否要扩容 338 resize(); 339 afterNodeInsertion(evict); 340 return null; 341 } 342 343 /** 344 * Initializes or doubles table size. 345 * @return the table 346 */ 347 final Node<K,V>[] resize() { 348 Node<K,V>[] oldTab = table; 349 int oldCap = (oldTab == null) ? 0 : oldTab.length; 350 int oldThr = threshold; 351 int newCap, newThr = 0; 352 if (oldCap > 0) { 353 if (oldCap >= MAXIMUM_CAPACITY) { 354 threshold = Integer.MAX_VALUE; 355 return oldTab; 356 } 357 else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY && oldCap >= DEFAULT_INITIAL_CAPACITY) //扩容,扩充为原来的两倍 358 newThr = oldThr << 1; // double threshold 359 } 360 else if (oldThr > 0) // initial capacity was placed in threshold 361 newCap = oldThr; 362 else { // zero initial threshold signifies using defaults 363 newCap = DEFAULT_INITIAL_CAPACITY; 364 newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY); 365 } 366 if (newThr == 0) { 367 float ft = (float)newCap * loadFactor; 368 newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ? (int)ft : Integer.MAX_VALUE); 369 } 370 threshold = newThr; 371 @SuppressWarnings({"rawtypes","unchecked"}) 372 Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap]; 373 table = newTab; 374 if (oldTab != null) { //扩容完成,进行数据拷贝 375 for (int j = 0; j < oldCap; ++j) { 376 Node<K,V> e; 377 if ((e = oldTab[j]) != null) { 378 oldTab[j] = null; 379 if (e.next == null) 380 newTab[e.hash & (newCap - 1)] = e; 381 else if (e instanceof TreeNode) 382 ((TreeNode<K,V>)e).split(this, newTab, j, oldCap); 383 else { // preserve order 384 Node<K,V> loHead = null, loTail = null; 385 Node<K,V> hiHead = null, hiTail = null; 386 Node<K,V> next; 387 do { 388 next = e.next; 389 if ((e.hash & oldCap) == 0) {//oldCap是2的次幂,最高位为1,其他位为0.按位与结果为0,说明hash比它小,原表有这个位置 390 if (loTail == null) 391 loHead = e; 392 else 393 loTail.next = e; 394 loTail = e; 395 } 396 else { 397 if (hiTail == null) 398 hiHead = e; 399 else 400 hiTail.next = e; 401 hiTail = e; 402 } 403 } while ((e = next) != null); 404 if (loTail != null) { 405 loTail.next = null; 406 newTab[j] = loHead; 407 } 408 if (hiTail != null) { 409 hiTail.next = null; 410 newTab[j + oldCap] = hiHead; 411 } 412 } 413 } 414 } 415 } 416 return newTab; 417 } 418 419 /** 420 * Replaces all linked nodes in bin at index for given hash unless table is too small, in which case resizes instead. 421 */ 422 final void treeifyBin(Node<K,V>[] tab, int hash) { 423 int n, index; Node<K,V> e; 424 if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY) //map大小小于64时,只扩容不树化 425 resize(); 426 else if ((e = tab[index = (n - 1) & hash]) != null) { 427 TreeNode<K,V> hd = null, tl = null; 428 do { 429 TreeNode<K,V> p = replacementTreeNode(e, null); 430 if (tl == null) 431 hd = p; 432 else { 433 p.prev = tl; 434 tl.next = p; 435 } 436 tl = p; 437 } while ((e = e.next) != null); 438 if ((tab[index] = hd) != null) 439 hd.treeify(tab); 440 } 441 } 442 443 /** 444 * Copies all of the mappings from the specified map to this map.*/ 445 public void putAll(Map<? extends K, ? extends V> m) { 446 putMapEntries(m, true); 447 } 448 449 /** 450 * Removes the mapping for the specified key from this map if present.*/ 451 public V remove(Object key) { 452 Node<K,V> e; 453 return (e = removeNode(hash(key), key, null, false, true)) == null ? null : e.value; 454 } 455 456 /** 457 * Implements Map.remove and related methods 458 * 459 * @param hash hash for key 460 * @param key the key 461 * @param value the value to match if matchValue, else ignored 462 * @param matchValue if true only remove if value is equal 463 * @param movable if false do not move other nodes while removing 464 * @return the node, or null if none 465 */ 466 final Node<K,V> removeNode(int hash, Object key, Object value,boolean matchValue, boolean movable) { 467 Node<K,V>[] tab; Node<K,V> p; int n, index; 468 if ((tab = table) != null && (n = tab.length) > 0 && 469 (p = tab[index = (n - 1) & hash]) != null) { 470 Node<K,V> node = null, e; K k; V v; 471 if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k)))) 472 node = p; 473 else if ((e = p.next) != null) { 474 if (p instanceof TreeNode) 475 node = ((TreeNode<K,V>)p).getTreeNode(hash, key); 476 else { 477 do { 478 if (e.hash == hash && 479 ((k = e.key) == key || 480 (key != null && key.equals(k)))) { 481 node = e; 482 break; 483 } 484 p = e; 485 } while ((e = e.next) != null); 486 } 487 } 488 if (node != null && (!matchValue || (v = node.value) == value ||(value != null && value.equals(v)))) { 489 if (node instanceof TreeNode) 490 ((TreeNode<K,V>)node).removeTreeNode(this, tab, movable); 491 else if (node == p) 492 tab[index] = node.next; 493 else 494 p.next = node.next; 495 ++modCount; 496 --size; 497 afterNodeRemoval(node); 498 return node; 499 } 500 } 501 return null; 502 } 503 504 /** 505 * Removes all of the mappings from this map.The map will be empty after this call returns. 506 */ 507 public void clear() { 508 Node<K,V>[] tab; 509 modCount++; 510 if ((tab = table) != null && size > 0) { 511 size = 0; 512 for (int i = 0; i < tab.length; ++i) 513 tab[i] = null; 514 } 515 } 516 517 /** 518 * Returns <tt>true</tt> if this map maps one or more keys to the specified value. 519 * @param value value whose presence in this map is to be tested 520 * @return <tt>true</tt> if this map maps one or more keys to the specified value 521 */ 522 public boolean containsValue(Object value) { 523 Node<K,V>[] tab; V v; 524 if ((tab = table) != null && size > 0) { 525 for (int i = 0; i < tab.length; ++i) { 526 for (Node<K,V> e = tab[i]; e != null; e = e.next) { 527 if ((v = e.value) == value || 528 (value != null && value.equals(v))) 529 return true; 530 } 531 } 532 } 533 return false; 534 } 535 536 // Overrides of JDK8 Map extension methods 537 538 @Override 539 public V getOrDefault(Object key, V defaultValue) { 540 Node<K,V> e; 541 return (e = getNode(hash(key), key)) == null ? defaultValue : e.value; 542 } 543 544 @Override 545 public V putIfAbsent(K key, V value) { 546 return putVal(hash(key), key, value, true, true); 547 } 548 549 @Override 550 public boolean remove(Object key, Object value) { 551 return removeNode(hash(key), key, value, true, true) != null; 552 } 553 554 @Override 555 public boolean replace(K key, V oldValue, V newValue) { 556 Node<K,V> e; V v; 557 if ((e = getNode(hash(key), key)) != null && 558 ((v = e.value) == oldValue || (v != null && v.equals(oldValue)))) { 559 e.value = newValue; 560 afterNodeAccess(e); 561 return true; 562 } 563 return false; 564 } 565 566 @Override 567 public V replace(K key, V value) { 568 Node<K,V> e; 569 if ((e = getNode(hash(key), key)) != null) { 570 V oldValue = e.value; 571 e.value = value; 572 afterNodeAccess(e); 573 return oldValue; 574 } 575 return null; 576 } 577 578 @Override 579 public void forEach(BiConsumer<? super K, ? super V> action) { 580 Node<K,V>[] tab; 581 if (action == null) 582 throw new NullPointerException(); 583 if (size > 0 && (tab = table) != null) { 584 int mc = modCount; 585 for (int i = 0; i < tab.length; ++i) { 586 for (Node<K,V> e = tab[i]; e != null; e = e.next) 587 action.accept(e.key, e.value); 588 } 589 if (modCount != mc) 590 throw new ConcurrentModificationException(); 591 } 592 } 593 594 @Override 595 public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) { 596 Node<K,V>[] tab; 597 if (function == null) 598 throw new NullPointerException(); 599 if (size > 0 && (tab = table) != null) { 600 int mc = modCount; 601 for (int i = 0; i < tab.length; ++i) { 602 for (Node<K,V> e = tab[i]; e != null; e = e.next) { 603 e.value = function.apply(e.key, e.value); 604 } 605 } 606 if (modCount != mc) 607 throw new ConcurrentModificationException(); 608 } 609 } 610 611 /* ------------------------------------------------------------ */ 612 // Cloning and serialization 613 614 /** 615 * Returns a shallow copy of this <tt>HashMap</tt> instance: the keys and values themselves are not cloned. 616 * 617 * @return a shallow copy of this map 618 */ 619 @SuppressWarnings("unchecked") 620 @Override 621 public Object clone() { 622 HashMap<K,V> result; 623 try { 624 result = (HashMap<K,V>)super.clone(); 625 } catch (CloneNotSupportedException e) { 626 // this shouldn't happen, since we are Cloneable 627 throw new InternalError(e); 628 } 629 result.reinitialize(); 630 result.putMapEntries(this, false); 631 return result; 632 } 633 634 // These methods are also used when serializing HashSets 635 final float loadFactor() { return loadFactor; } 636 final int capacity() { 637 return (table != null) ? table.length : (threshold > 0) ? threshold : DEFAULT_INITIAL_CAPACITY; 638 }/* ------------------------------------------------------------ */ 639 // LinkedHashMap support 640 641 642 /* 643 * The following package-protected methods are designed to be 644 * overridden by LinkedHashMap, but not by any other subclass. 645 * Nearly all other internal methods are also package-protected 646 * but are declared final, so can be used by LinkedHashMap, view 647 * classes, and HashSet. 648 */ 649 650 // Create a regular (non-tree) node 651 Node<K,V> newNode(int hash, K key, V value, Node<K,V> next) { 652 return new Node<>(hash, key, value, next); 653 } 654 655 // For conversion from TreeNodes to plain nodes 656 Node<K,V> replacementNode(Node<K,V> p, Node<K,V> next) { 657 return new Node<>(p.hash, p.key, p.value, next); 658 } 659 660 // Create a tree bin node 661 TreeNode<K,V> newTreeNode(int hash, K key, V value, Node<K,V> next) { 662 return new TreeNode<>(hash, key, value, next); 663 } 664 665 // For treeifyBin 666 TreeNode<K,V> replacementTreeNode(Node<K,V> p, Node<K,V> next) { 667 return new TreeNode<>(p.hash, p.key, p.value, next); 668 } 669 670 /** 671 * Reset to initial default state. Called by clone and readObject. 672 */ 673 void reinitialize() { 674 table = null; 675 entrySet = null; 676 keySet = null; 677 values = null; 678 modCount = 0; 679 threshold = 0; 680 size = 0; 681 } 682 683 // Callbacks to allow LinkedHashMap post-actions 684 void afterNodeAccess(Node<K,V> p) { } 685 void afterNodeInsertion(boolean evict) { } 686 void afterNodeRemoval(Node<K,V> p) { } 687 688 // Called only from writeObject, to ensure compatible ordering. 689 void internalWriteEntries(java.io.ObjectOutputStream s) throws IOException { 690 Node<K,V>[] tab; 691 if (size > 0 && (tab = table) != null) { 692 for (int i = 0; i < tab.length; ++i) { 693 for (Node<K,V> e = tab[i]; e != null; e = e.next) { 694 s.writeObject(e.key); 695 s.writeObject(e.value); 696 } 697 } 698 } 699 } 700 701 }
总结:
1.MAXIMUM_CAPACITY 是数组最大的长度2的30次方,原因是2的31次方就超过Integer.MAX_VALUE(2147483647)了(也就是2^31-1)
2.HashMap有两个参数影响其性能:初始容量和加载因子。默认初始容量是16,加载因子是0.75。容量是哈希表中桶(Entry数组)的数量,初始容量只是哈希表在创建时的容量。加载因子是哈希表在其容量自动增加之前可以达到多满的一种尺度。当哈希表中的条目数超出了加载因子与当前容量的乘积时,通过调用 rehash 方法将容量翻倍。
3.transient是Java语言的关键字,用来表示一个域不是该对象串行化的一部分。当一个对象被串行化的时候,transient型变量的值不包括在串行化的表示中,也就是说没法持久化。
4.在扩容过程中,树化要满足两个条件:链表长度大于等于 TREEIFY_THRESHOLD、桶数组容量大于等于 MIN_TREEIFY_CAPACITY
其他hashcode相关内容见 源码分析之Map(二)HashCode详解
HashMap.TreeNode源码解析
TreeNode不仅是红黑树,还是链表。继承了LinkedHashMap.Entry,而Entry继承了 HashMap.Node
1 public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable { 2 3 4 static final class TreeNode<K,V> extends LinkedHashMap.Entry<K,V> { 5 TreeNode<K,V> parent; // red-black tree links 6 TreeNode<K,V> left; 7 TreeNode<K,V> right; 8 TreeNode<K,V> prev; // needed to unlink next upon deletion 前一个录入节点,删除后需要取消链接 9 boolean red; 10 TreeNode(int hash, K key, V val, Node<K,V> next) { 11 super(hash, key, val, next); 12 } 13 14 /** 15 * Returns root of tree containing this node. 获取root节点 16 */ 17 final TreeNode<K,V> root() { 18 for (TreeNode<K,V> r = this, p;;) { 19 if ((p = r.parent) == null) 20 return r; 21 r = p; 22 } 23 } 24 25 /** 26 * Ensures that the given root is the first node of its bin. * 移动root节点到前面,然后确认是否符合红黑树性质 27 */ 28 static <K,V> void moveRootToFront(Node<K,V>[] tab, TreeNode<K,V> root) { 29 int n; 30 if (root != null && tab != null && (n = tab.length) > 0) { 31 int index = (n - 1) & root.hash; //树在数组中的下标 32 TreeNode<K,V> first = (TreeNode<K,V>)tab[index]; 33 if (root != first) { 34 Node<K,V> rn; 35 tab[index] = root; //将传入的root放在此位置 36 TreeNode<K,V> rp = root.prev; 37 if ((rn = root.next) != null) //root的后一个节点不为null 38 ((TreeNode<K,V>)rn).prev = rp; //root的前节点指向root的后节点的前节点,相当于移除root 39 if (rp != null) 40 rp.next = rn; 41 if (first != null) 42 first.prev = root; //原首节点的前一个指向root 43 root.next = first; //root的下一个节点指向原首节点 44 root.prev = null; 45 } 46 assert checkInvariants(root); 47 } 48 } 49 50 /** 51 * Finds the node starting at root p with the given hash and key. 52 * The kc argument caches comparableClassFor(key) upon first use 53 * comparing keys. 以该节点作为根节点,查找对象k h是k的hash值 */ 54 final TreeNode<K,V> find(int h, Object k, Class<?> kc) { 55 TreeNode<K,V> p = this; 56 do { 57 int ph, dir; K pk; 58 TreeNode<K,V> pl = p.left, pr = p.right, q; 59 if ((ph = p.hash) > h) //如果当前节点的hash值大于k的hash值,那么后续应该让k和左孩子节点进行下一轮比较 60 p = pl; 61 else if (ph < h) 62 p = pr; 63 else if ((pk = p.key) == k || (k != null && k.equals(pk))) //地址相同或equals相同 64 return p; //返回当前节点 65 else if (pl == null) 66 p = pr; 67 else if (pr == null) 68 p = pl; 69 else if ((kc != null || (kc = comparableClassFor(k)) != null) && (dir = compareComparables(kc, k, pk)) != 0) 70 p = (dir < 0) ? pl : pr; 71 else if ((q = pr.find(h, k, kc)) != null) //从右孩子节点递归循环查找,如果匹配则返回 72 return q; 73 else 74 p = pl; 75 } while (p != null); 76 return null; 77 } 78 79 /** 80 * Calls find for root node. 81 */ 82 final TreeNode<K,V> getTreeNode(int h, Object k) { 83 return ((parent != null) ? root() : this).find(h, k, null); 84 } 85 86 /** 87 * Tie-breaking utility for ordering insertions when equal hashCodes and non-comparable. We don't require a total 88 * order, just a consistent insertion rule to maintain equivalence across rebalancings. Tie-breaking further than 89 * necessary simplifies testing a bit. 90 */ 91 static int tieBreakOrder(Object a, Object b) { 92 int d; 93 if (a == null || b == null || 94 (d = a.getClass().getName(). 95 compareTo(b.getClass().getName())) == 0) 96 d = (System.identityHashCode(a) <= System.identityHashCode(b) ? 97 -1 : 1); 98 return d; 99 } 100 101 /** 102 * Forms tree of the nodes linked from this node. 从当前节点开始,遍历列表,往红黑树里插入。插入后平衡处理 103 * @return root of tree 104 */ 105 final void treeify(Node<K,V>[] tab) { 106 TreeNode<K,V> root = null; 107 for (TreeNode<K,V> x = this, next; x != null; x = next) { 108 next = (TreeNode<K,V>)x.next; 109 x.left = x.right = null; 110 if (root == null) { //设置第一个节点为根节点,颜色为黑色 111 x.parent = null; 112 x.red = false; 113 root = x; 114 } 115 else { 116 K k = x.key; 117 int h = x.hash; 118 Class<?> kc = null; 119 for (TreeNode<K,V> p = root;;) { 120 int dir, ph; 121 K pk = p.key; 122 if ((ph = p.hash) > h) 123 dir = -1; 124 else if (ph < h) 125 dir = 1; 126 else if ((kc == null && 127 (kc = comparableClassFor(k)) == null) || 128 (dir = compareComparables(kc, k, pk)) == 0) 129 dir = tieBreakOrder(k, pk); 130 131 TreeNode<K,V> xp = p; 132 if ((p = (dir <= 0) ? p.left : p.right) == null) {//dir小于等于0,指向左子树,反之右子树,如果为null直接插入,不为null则继续遍历 133 x.parent = xp; 134 if (dir <= 0) 135 xp.left = x; 136 else 137 xp.right = x; 138 root = balanceInsertion(root, x); //红黑树平衡 139 break; 140 } 141 } 142 } 143 } 144 moveRootToFront(tab, root);//把根节点指向桶节点 145 } 146 147 /** 148 * Returns a list of non-TreeNodes replacing those linked from 149 * this node. 红黑树转链表 150 */ 151 final Node<K,V> untreeify(HashMap<K,V> map) { 152 Node<K,V> hd = null, tl = null; 153 for (Node<K,V> q = this; q != null; q = q.next) { 154 Node<K,V> p = map.replacementNode(q, null); 155 if (tl == null) 156 hd = p; 157 else 158 tl.next = p; 159 tl = p; 160 } 161 return hd; 162 } 163 164 /** 165 * Tree version of putVal. 166 */ 167 final TreeNode<K,V> putTreeVal(HashMap<K,V> map, Node<K,V>[] tab, int h, K k, V v) { 168 Class<?> kc = null; 169 boolean searched = false; 170 TreeNode<K,V> root = (parent != null) ? root() : this; 171 for (TreeNode<K,V> p = root;;) { 172 int dir, ph; K pk; 173 if ((ph = p.hash) > h) 174 dir = -1; 175 else if (ph < h) 176 dir = 1; 177 else if ((pk = p.key) == k || (k != null && k.equals(pk))) 178 return p; 179 else if ((kc == null && 180 (kc = comparableClassFor(k)) == null) || 181 (dir = compareComparables(kc, k, pk)) == 0) { 182 if (!searched) { 183 TreeNode<K,V> q, ch; 184 searched = true; 185 if (((ch = p.left) != null && 186 (q = ch.find(h, k, kc)) != null) || 187 ((ch = p.right) != null && 188 (q = ch.find(h, k, kc)) != null)) 189 return q; 190 } 191 dir = tieBreakOrder(k, pk); 192 } 193 194 TreeNode<K,V> xp = p; 195 if ((p = (dir <= 0) ? p.left : p.right) == null) { 196 Node<K,V> xpn = xp.next; 197 TreeNode<K,V> x = map.newTreeNode(h, k, v, xpn); 198 if (dir <= 0) 199 xp.left = x; 200 else 201 xp.right = x; 202 xp.next = x; 203 x.parent = x.prev = xp; 204 if (xpn != null) 205 ((TreeNode<K,V>)xpn).prev = x; 206 moveRootToFront(tab, balanceInsertion(root, x)); 207 return null; 208 } 209 } 210 } 211 212 /** 213 * Removes the given node, that must be present before this call. 214 */ 215 final void removeTreeNode(HashMap<K,V> map, Node<K,V>[] tab, 216 boolean movable) { 217 int n; 218 if (tab == null || (n = tab.length) == 0) 219 return; 220 int index = (n - 1) & hash; 221 TreeNode<K,V> first = (TreeNode<K,V>)tab[index], root = first, rl; 222 TreeNode<K,V> succ = (TreeNode<K,V>)next, pred = prev; 223 if (pred == null) 224 tab[index] = first = succ; 225 else 226 pred.next = succ; 227 if (succ != null) 228 succ.prev = pred; 229 if (first == null) 230 return; 231 if (root.parent != null) 232 root = root.root(); 233 if (root == null || root.right == null || 234 (rl = root.left) == null || rl.left == null) { 235 tab[index] = first.untreeify(map); // too small 236 return; 237 } 238 TreeNode<K,V> p = this, pl = left, pr = right, replacement; 239 if (pl != null && pr != null) { 240 TreeNode<K,V> s = pr, sl; 241 while ((sl = s.left) != null) // find successor 242 s = sl; 243 boolean c = s.red; s.red = p.red; p.red = c; // swap colors 244 TreeNode<K,V> sr = s.right; 245 TreeNode<K,V> pp = p.parent; 246 if (s == pr) { // p was s's direct parent 247 p.parent = s; 248 s.right = p; 249 } 250 else { 251 TreeNode<K,V> sp = s.parent; 252 if ((p.parent = sp) != null) { 253 if (s == sp.left) 254 sp.left = p; 255 else 256 sp.right = p; 257 } 258 if ((s.right = pr) != null) 259 pr.parent = s; 260 } 261 p.left = null; 262 if ((p.right = sr) != null) 263 sr.parent = p; 264 if ((s.left = pl) != null) 265 pl.parent = s; 266 if ((s.parent = pp) == null) 267 root = s; 268 else if (p == pp.left) 269 pp.left = s; 270 else 271 pp.right = s; 272 if (sr != null) 273 replacement = sr; 274 else 275 replacement = p; 276 } 277 else if (pl != null) 278 replacement = pl; 279 else if (pr != null) 280 replacement = pr; 281 else 282 replacement = p; 283 if (replacement != p) { 284 TreeNode<K,V> pp = replacement.parent = p.parent; 285 if (pp == null) 286 root = replacement; 287 else if (p == pp.left) 288 pp.left = replacement; 289 else 290 pp.right = replacement; 291 p.left = p.right = p.parent = null; 292 } 293 294 TreeNode<K,V> r = p.red ? root : balanceDeletion(root, replacement); 295 296 if (replacement == p) { // detach 297 TreeNode<K,V> pp = p.parent; 298 p.parent = null; 299 if (pp != null) { 300 if (p == pp.left) 301 pp.left = null; 302 else if (p == pp.right) 303 pp.right = null; 304 } 305 } 306 if (movable) 307 moveRootToFront(tab, r); 308 } 309 310 /** 311 * Splits nodes in a tree bin into lower and upper tree bins, 312 * or untreeifies if now too small. Called only from resize; 313 * see above discussion about split bits and indices. 314 * 315 * @param map the map 316 * @param tab the table for recording bin heads 317 * @param index the index of the table being split 318 * @param bit the bit of hash to split on 319 */ 320 final void split(HashMap<K,V> map, Node<K,V>[] tab, int index, int bit) { 321 TreeNode<K,V> b = this; 322 // Relink into lo and hi lists, preserving order 323 TreeNode<K,V> loHead = null, loTail = null; 324 TreeNode<K,V> hiHead = null, hiTail = null; 325 int lc = 0, hc = 0; 326 for (TreeNode<K,V> e = b, next; e != null; e = next) { 327 next = (TreeNode<K,V>)e.next; 328 e.next = null; 329 if ((e.hash & bit) == 0) { 330 if ((e.prev = loTail) == null) 331 loHead = e; 332 else 333 loTail.next = e; 334 loTail = e; 335 ++lc; 336 } 337 else { 338 if ((e.prev = hiTail) == null) 339 hiHead = e; 340 else 341 hiTail.next = e; 342 hiTail = e; 343 ++hc; 344 } 345 } 346 347 if (loHead != null) { 348 if (lc <= UNTREEIFY_THRESHOLD) 349 tab[index] = loHead.untreeify(map); 350 else { 351 tab[index] = loHead; 352 if (hiHead != null) // (else is already treeified) 353 loHead.treeify(tab); 354 } 355 } 356 if (hiHead != null) { 357 if (hc <= UNTREEIFY_THRESHOLD) 358 tab[index + bit] = hiHead.untreeify(map); 359 else { 360 tab[index + bit] = hiHead; 361 if (loHead != null) 362 hiHead.treeify(tab); 363 } 364 } 365 } 366 367 /* ------------------------------------------------------------ */ 368 // Red-black tree methods, all adapted from CLR // 进行左旋的是当前节点⑤和它的右节点12。12取代⑤的位置;⑤变成12的左节点;⑦点变成⑤的右节点 369 370 static <K,V> TreeNode<K,V> rotateLeft(TreeNode<K,V> root,TreeNode<K,V> p) { 371 TreeNode<K,V> r, pp, rl; 372 if (p != null && (r = p.right) != null) { 373 if ((rl = p.right = r.left) != null) 374 rl.parent = p; 375 if ((pp = r.parent = p.parent) == null) 376 (root = r).red = false; 377 else if (pp.left == p) 378 pp.left = r; 379 else 380 pp.right = r; 381 r.left = p; 382 p.parent = r; 383 } 384 return root; 385 } 386 //进行右旋的是当前节点19和它的左节点12。12取代19的位置;19变成12的右节点;13变成19的左节点 387 static <K,V> TreeNode<K,V> rotateRight(TreeNode<K,V> root, TreeNode<K,V> p) { 388 TreeNode<K,V> l, pp, lr; 389 if (p != null && (l = p.left) != null) { 390 if ((lr = p.left = l.right) != null) 391 lr.parent = p; 392 if ((pp = l.parent = p.parent) == null) 393 (root = l).red = false; 394 else if (pp.right == p) 395 pp.right = l; 396 else 397 pp.left = l; 398 l.right = p; 399 p.parent = l; 400 } 401 return root; 402 } 403 404 static <K,V> TreeNode<K,V> balanceInsertion(TreeNode<K,V> root,TreeNode<K,V> x) { 405 x.red = true; 406 for (TreeNode<K,V> xp, xpp, xppl, xppr;;) { 407 if ((xp = x.parent) == null) { 408 x.red = false; 409 return x; 410 } 411 else if (!xp.red || (xpp = xp.parent) == null) 412 return root; 413 if (xp == (xppl = xpp.left)) { 414 if ((xppr = xpp.right) != null && xppr.red) { 415 xppr.red = false; 416 xp.red = false; 417 xpp.red = true; 418 x = xpp; 419 } 420 else { 421 if (x == xp.right) { 422 root = rotateLeft(root, x = xp); 423 xpp = (xp = x.parent) == null ? null : xp.parent; 424 } 425 if (xp != null) { 426 xp.red = false; 427 if (xpp != null) { 428 xpp.red = true; 429 root = rotateRight(root, xpp); 430 } 431 } 432 } 433 } 434 else { 435 if (xppl != null && xppl.red) { 436 xppl.red = false; 437 xp.red = false; 438 xpp.red = true; 439 x = xpp; 440 } 441 else { 442 if (x == xp.left) { 443 root = rotateRight(root, x = xp); 444 xpp = (xp = x.parent) == null ? null : xp.parent; 445 } 446 if (xp != null) { 447 xp.red = false; 448 if (xpp != null) { 449 xpp.red = true; 450 root = rotateLeft(root, xpp); 451 } 452 } 453 } 454 } 455 } 456 } 457 458 static <K,V> TreeNode<K,V> balanceDeletion(TreeNode<K,V> root,TreeNode<K,V> x) { 459 for (TreeNode<K,V> xp, xpl, xpr;;) { 460 if (x == null || x == root) 461 return root; 462 else if ((xp = x.parent) == null) { 463 x.red = false; 464 return x; 465 } 466 else if (x.red) { 467 x.red = false; 468 return root; 469 } 470 else if ((xpl = xp.left) == x) { 471 if ((xpr = xp.right) != null && xpr.red) { 472 xpr.red = false; 473 xp.red = true; 474 root = rotateLeft(root, xp); 475 xpr = (xp = x.parent) == null ? null : xp.right; 476 } 477 if (xpr == null) 478 x = xp; 479 else { 480 TreeNode<K,V> sl = xpr.left, sr = xpr.right; 481 if ((sr == null || !sr.red) && 482 (sl == null || !sl.red)) { 483 xpr.red = true; 484 x = xp; 485 } 486 else { 487 if (sr == null || !sr.red) { 488 if (sl != null) 489 sl.red = false; 490 xpr.red = true; 491 root = rotateRight(root, xpr); 492 xpr = (xp = x.parent) == null ? 493 null : xp.right; 494 } 495 if (xpr != null) { 496 xpr.red = (xp == null) ? false : xp.red; 497 if ((sr = xpr.right) != null) 498 sr.red = false; 499 } 500 if (xp != null) { 501 xp.red = false; 502 root = rotateLeft(root, xp); 503 } 504 x = root; 505 } 506 } 507 } 508 else { // symmetric 509 if (xpl != null && xpl.red) { 510 xpl.red = false; 511 xp.red = true; 512 root = rotateRight(root, xp); 513 xpl = (xp = x.parent) == null ? null : xp.left; 514 } 515 if (xpl == null) 516 x = xp; 517 else { 518 TreeNode<K,V> sl = xpl.left, sr = xpl.right; 519 if ((sl == null || !sl.red) && 520 (sr == null || !sr.red)) { 521 xpl.red = true; 522 x = xp; 523 } 524 else { 525 if (sl == null || !sl.red) { 526 if (sr != null) 527 sr.red = false; 528 xpl.red = true; 529 root = rotateLeft(root, xpl); 530 xpl = (xp = x.parent) == null ? 531 null : xp.left; 532 } 533 if (xpl != null) { 534 xpl.red = (xp == null) ? false : xp.red; 535 if ((sl = xpl.left) != null) 536 sl.red = false; 537 } 538 if (xp != null) { 539 xp.red = false; 540 root = rotateRight(root, xp); 541 } 542 x = root; 543 } 544 } 545 } 546 } 547 } 548 549 /** 550 * Recursive invariant check 551 */ 552 static <K,V> boolean checkInvariants(TreeNode<K,V> t) { 553 TreeNode<K,V> tp = t.parent, tl = t.left, tr = t.right, 554 tb = t.prev, tn = (TreeNode<K,V>)t.next; 555 if (tb != null && tb.next != t) 556 return false; 557 if (tn != null && tn.prev != t) 558 return false; 559 if (tp != null && t != tp.left && t != tp.right) 560 return false; 561 if (tl != null && (tl.parent != t || tl.hash > t.hash)) 562 return false; 563 if (tr != null && (tr.parent != t || tr.hash < t.hash)) 564 return false; 565 if (t.red && tl != null && tl.red && tr != null && tr.red) 566 return false; 567 if (tl != null && !checkInvariants(tl)) 568 return false; 569 if (tr != null && !checkInvariants(tr)) 570 return false; 571 return true; 572 } 573 }}
红黑树的特性见 数据结构之树(三)
参照:https://blog.csdn.net/sun112233445/article/details/103350026