Java工具类——HashMap源码分析
1 /* 2 * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. 3 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13 * 14 * 15 * 16 * 17 * 18 * 19 * 20 * 21 * 22 * 23 * 24 */ 25 26 package java.util; 27 import java.io.*; 28 29 /** 30 * Hash table based implementation of the <tt>Map</tt> interface. This 31 * implementation provides all of the optional map operations, and permits 32 * <tt>null</tt> values and the <tt>null</tt> key. (The <tt>HashMap</tt> 33 * class is roughly equivalent to <tt>Hashtable</tt>, except that it is 34 * unsynchronized and permits nulls.) This class makes no guarantees as to 35 * the order of the map; in particular, it does not guarantee that the order 36 * will remain constant over time. 37 * 38 * <p>This implementation provides constant-time performance for the basic 39 * operations (<tt>get</tt> and <tt>put</tt>), assuming the hash function 40 * disperses the elements properly among the buckets. Iteration over 41 * collection views requires time proportional to the "capacity" of the 42 * <tt>HashMap</tt> instance (the number of buckets) plus its size (the number 43 * of key-value mappings). Thus, it's very important not to set the initial 44 * capacity too high (or the load factor too low) if iteration performance is 45 * important. 46 * 47 * <p>An instance of <tt>HashMap</tt> has two parameters that affect its 48 * performance: <i>initial capacity</i> and <i>load factor</i>. The 49 * <i>capacity</i> is the number of buckets in the hash table, and the initial 50 * capacity is simply the capacity at the time the hash table is created. The 51 * <i>load factor</i> is a measure of how full the hash table is allowed to 52 * get before its capacity is automatically increased. When the number of 53 * entries in the hash table exceeds the product of the load factor and the 54 * current capacity, the hash table is <i>rehashed</i> (that is, internal data 55 * structures are rebuilt) so that the hash table has approximately twice the 56 * number of buckets. 57 * 58 * <p>As a general rule, the default load factor (.75) offers a good tradeoff 59 * between time and space costs. Higher values decrease the space overhead 60 * but increase the lookup cost (reflected in most of the operations of the 61 * <tt>HashMap</tt> class, including <tt>get</tt> and <tt>put</tt>). The 62 * expected number of entries in the map and its load factor should be taken 63 * into account when setting its initial capacity, so as to minimize the 64 * number of rehash operations. If the initial capacity is greater 65 * than the maximum number of entries divided by the load factor, no 66 * rehash operations will ever occur. 67 * 68 * <p>If many mappings are to be stored in a <tt>HashMap</tt> instance, 69 * creating it with a sufficiently large capacity will allow the mappings to 70 * be stored more efficiently than letting it perform automatic rehashing as 71 * needed to grow the table. 72 * 73 * <p><strong>Note that this implementation is not synchronized.</strong> 74 * If multiple threads access a hash map concurrently, and at least one of 75 * the threads modifies the map structurally, it <i>must</i> be 76 * synchronized externally. (A structural modification is any operation 77 * that adds or deletes one or more mappings; merely changing the value 78 * associated with a key that an instance already contains is not a 79 * structural modification.) This is typically accomplished by 80 * synchronizing on some object that naturally encapsulates the map. 81 * 82 * If no such object exists, the map should be "wrapped" using the 83 * {@link Collections#synchronizedMap Collections.synchronizedMap} 84 * method. This is best done at creation time, to prevent accidental 85 * unsynchronized access to the map:<pre> 86 * Map m = Collections.synchronizedMap(new HashMap(...));</pre> 87 * 88 * <p>The iterators returned by all of this class's "collection view methods" 89 * are <i>fail-fast</i>: if the map is structurally modified at any time after 90 * the iterator is created, in any way except through the iterator's own 91 * <tt>remove</tt> method, the iterator will throw a 92 * {@link ConcurrentModificationException}. Thus, in the face of concurrent 93 * modification, the iterator fails quickly and cleanly, rather than risking 94 * arbitrary, non-deterministic behavior at an undetermined time in the 95 * future. 96 * 97 * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed 98 * as it is, generally speaking, impossible to make any hard guarantees in the 99 * presence of unsynchronized concurrent modification. Fail-fast iterators 100 * throw <tt>ConcurrentModificationException</tt> on a best-effort basis. 101 * Therefore, it would be wrong to write a program that depended on this 102 * exception for its correctness: <i>the fail-fast behavior of iterators 103 * should be used only to detect bugs.</i> 104 * 105 * <p>This class is a member of the 106 * <a href="{@docRoot}/../technotes/guides/collections/index.html"> 107 * Java Collections Framework</a>. 108 * 109 * @param <K> the type of keys maintained by this map 110 * @param <V> the type of mapped values 111 * 112 * @author Doug Lea 113 * @author Josh Bloch 114 * @author Arthur van Hoff 115 * @author Neal Gafter 116 * @see Object#hashCode() 117 * @see Collection 118 * @see Map 119 * @see TreeMap 120 * @see Hashtable 121 * @since 1.2 122 */ 123 124 public class HashMap<K,V> 125 extends AbstractMap<K,V> 126 implements Map<K,V>, Cloneable, Serializable 127 { 128 129 /** 130 * The default initial capacity - MUST be a power of two. 131 */ 132 static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16 133 134 /** 135 * The maximum capacity, used if a higher value is implicitly specified 136 * by either of the constructors with arguments. 137 * MUST be a power of two <= 1<<30. 138 */ 139 static final int MAXIMUM_CAPACITY = 1 << 30; 140 141 /** 142 * The load factor used when none specified in constructor. 143 */ 144 static final float DEFAULT_LOAD_FACTOR = 0.75f; 145 146 /** 147 * An empty table instance to share when the table is not inflated. 148 */ 149 static final Entry<?,?>[] EMPTY_TABLE = {}; 150 151 /** 152 * The table, resized as necessary. Length MUST Always be a power of two. 153 */ 154 transient Entry<K,V>[] table = (Entry<K,V>[]) EMPTY_TABLE; 155 156 /** 157 * The number of key-value mappings contained in this map. 158 */ 159 transient int size; 160 161 /** 162 * The next size value at which to resize (capacity * load factor). 163 * @serial 164 */ 165 // If table == EMPTY_TABLE then this is the initial capacity at which the 166 // table will be created when inflated. 167 int threshold; 168 169 /** 170 * The load factor for the hash table. 171 * 172 * @serial 173 */ 174 final float loadFactor; 175 176 /** 177 * The number of times this HashMap has been structurally modified 178 * Structural modifications are those that change the number of mappings in 179 * the HashMap or otherwise modify its internal structure (e.g., 180 * rehash). This field is used to make iterators on Collection-views of 181 * the HashMap fail-fast. (See ConcurrentModificationException). 182 */ 183 transient int modCount; 184 185 /** 186 * The default threshold of map capacity above which alternative hashing is 187 * used for String keys. Alternative hashing reduces the incidence of 188 * collisions due to weak hash code calculation for String keys. 189 * <p/> 190 * This value may be overridden by defining the system property 191 * {@code jdk.map.althashing.threshold}. A property value of {@code 1} 192 * forces alternative hashing to be used at all times whereas 193 * {@code -1} value ensures that alternative hashing is never used. 194 */ 195 static final int ALTERNATIVE_HASHING_THRESHOLD_DEFAULT = Integer.MAX_VALUE; 196 197 /** 198 * holds values which can't be initialized until after VM is booted. 199 */ 200 private static class Holder { 201 202 /** 203 * Table capacity above which to switch to use alternative hashing. 204 */ 205 static final int ALTERNATIVE_HASHING_THRESHOLD; 206 207 static { 208 String altThreshold = java.security.AccessController.doPrivileged( 209 new sun.security.action.GetPropertyAction( 210 "jdk.map.althashing.threshold")); 211 212 int threshold; 213 try { 214 threshold = (null != altThreshold) 215 ? Integer.parseInt(altThreshold) 216 : ALTERNATIVE_HASHING_THRESHOLD_DEFAULT; 217 218 // disable alternative hashing if -1 219 if (threshold == -1) { 220 threshold = Integer.MAX_VALUE; 221 } 222 223 if (threshold < 0) { 224 throw new IllegalArgumentException("value must be positive integer."); 225 } 226 } catch(IllegalArgumentException failed) { 227 throw new Error("Illegal value for 'jdk.map.althashing.threshold'", failed); 228 } 229 230 ALTERNATIVE_HASHING_THRESHOLD = threshold; 231 } 232 } 233 234 /** 235 * A randomizing value associated with this instance that is applied to 236 * hash code of keys to make hash collisions harder to find. If 0 then 237 * alternative hashing is disabled. 238 */ 239 transient int hashSeed = 0; 240 241 /** 242 * Constructs an empty <tt>HashMap</tt> with the specified initial 243 * capacity and load factor. 244 * 245 * @param initialCapacity the initial capacity 246 * @param loadFactor the load factor 247 * @throws IllegalArgumentException if the initial capacity is negative 248 * or the load factor is nonpositive 249 */ 250 public HashMap(int initialCapacity, float loadFactor) { 251 if (initialCapacity < 0) 252 throw new IllegalArgumentException("Illegal initial capacity: " + 253 initialCapacity); 254 if (initialCapacity > MAXIMUM_CAPACITY) 255 initialCapacity = MAXIMUM_CAPACITY; 256 if (loadFactor <= 0 || Float.isNaN(loadFactor)) 257 throw new IllegalArgumentException("Illegal load factor: " + 258 loadFactor); 259 260 this.loadFactor = loadFactor; 261 threshold = initialCapacity; 262 init(); 263 } 264 265 /** 266 * Constructs an empty <tt>HashMap</tt> with the specified initial 267 * capacity and the default load factor (0.75). 268 * 269 * @param initialCapacity the initial capacity. 270 * @throws IllegalArgumentException if the initial capacity is negative. 271 */ 272 public HashMap(int initialCapacity) { 273 this(initialCapacity, DEFAULT_LOAD_FACTOR); 274 } 275 276 /** 277 * Constructs an empty <tt>HashMap</tt> with the default initial capacity 278 * (16) and the default load factor (0.75). 279 */ 280 public HashMap() { 281 this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR); 282 } 283 284 /** 285 * Constructs a new <tt>HashMap</tt> with the same mappings as the 286 * specified <tt>Map</tt>. The <tt>HashMap</tt> is created with 287 * default load factor (0.75) and an initial capacity sufficient to 288 * hold the mappings in the specified <tt>Map</tt>. 289 * 290 * @param m the map whose mappings are to be placed in this map 291 * @throws NullPointerException if the specified map is null 292 */ 293 public HashMap(Map<? extends K, ? extends V> m) { 294 this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1, 295 DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR); 296 inflateTable(threshold); 297 298 putAllForCreate(m); 299 } 300 301 private static int roundUpToPowerOf2(int number) { 302 // assert number >= 0 : "number must be non-negative"; 303 int rounded = number >= MAXIMUM_CAPACITY 304 ? MAXIMUM_CAPACITY 305 : (rounded = Integer.highestOneBit(number)) != 0 306 ? (Integer.bitCount(number) > 1) ? rounded << 1 : rounded 307 : 1; 308 309 return rounded; 310 } 311 312 /** 313 * Inflates the table. 314 */ 315 private void inflateTable(int toSize) { 316 // Find a power of 2 >= toSize 317 int capacity = roundUpToPowerOf2(toSize); 318 319 threshold = (int) Math.min(capacity * loadFactor, MAXIMUM_CAPACITY + 1); 320 table = new Entry[capacity]; 321 initHashSeedAsNeeded(capacity); 322 } 323 324 // internal utilities 325 326 /** 327 * Initialization hook for subclasses. This method is called 328 * in all constructors and pseudo-constructors (clone, readObject) 329 * after HashMap has been initialized but before any entries have 330 * been inserted. (In the absence of this method, readObject would 331 * require explicit knowledge of subclasses.) 332 */ 333 void init() { 334 } 335 336 /** 337 * Initialize the hashing mask value. We defer initialization until we 338 * really need it. 339 */ 340 final boolean initHashSeedAsNeeded(int capacity) { 341 boolean currentAltHashing = hashSeed != 0; 342 boolean useAltHashing = sun.misc.VM.isBooted() && 343 (capacity >= Holder.ALTERNATIVE_HASHING_THRESHOLD); 344 boolean switching = currentAltHashing ^ useAltHashing; 345 if (switching) { 346 hashSeed = useAltHashing 347 ? sun.misc.Hashing.randomHashSeed(this) 348 : 0; 349 } 350 return switching; 351 } 352 353 /** 354 * Retrieve object hash code and applies a supplemental hash function to the 355 * result hash, which defends against poor quality hash functions. This is 356 * critical because HashMap uses power-of-two length hash tables, that 357 * otherwise encounter collisions for hashCodes that do not differ 358 * in lower bits. Note: Null keys always map to hash 0, thus index 0. 359 */ 360 final int hash(Object k) { 361 int h = hashSeed; 362 if (0 != h && k instanceof String) { 363 return sun.misc.Hashing.stringHash32((String) k); 364 } 365 366 h ^= k.hashCode(); 367 368 // This function ensures that hashCodes that differ only by 369 // constant multiples at each bit position have a bounded 370 // number of collisions (approximately 8 at default load factor). 371 h ^= (h >>> 20) ^ (h >>> 12); 372 return h ^ (h >>> 7) ^ (h >>> 4); 373 } 374 375 /** 376 * Returns index for hash code h. 377 */ 378 static int indexFor(int h, int length) { 379 // assert Integer.bitCount(length) == 1 : "length must be a non-zero power of 2"; 380 return h & (length-1); 381 } 382 383 /** 384 * Returns the number of key-value mappings in this map. 385 * 386 * @return the number of key-value mappings in this map 387 */ 388 public int size() { 389 return size; 390 } 391 392 /** 393 * Returns <tt>true</tt> if this map contains no key-value mappings. 394 * 395 * @return <tt>true</tt> if this map contains no key-value mappings 396 */ 397 public boolean isEmpty() { 398 return size == 0; 399 } 400 401 /** 402 * Returns the value to which the specified key is mapped, 403 * or {@code null} if this map contains no mapping for the key. 404 * 405 * <p>More formally, if this map contains a mapping from a key 406 * {@code k} to a value {@code v} such that {@code (key==null ? k==null : 407 * key.equals(k))}, then this method returns {@code v}; otherwise 408 * it returns {@code null}. (There can be at most one such mapping.) 409 * 410 * <p>A return value of {@code null} does not <i>necessarily</i> 411 * indicate that the map contains no mapping for the key; it's also 412 * possible that the map explicitly maps the key to {@code null}. 413 * The {@link #containsKey containsKey} operation may be used to 414 * distinguish these two cases. 415 * 416 * @see #put(Object, Object) 417 */ 418 public V get(Object key) { 419 if (key == null) 420 return getForNullKey(); 421 Entry<K,V> entry = getEntry(key); 422 423 return null == entry ? null : entry.getValue(); 424 } 425 426 /** 427 * Offloaded version of get() to look up null keys. Null keys map 428 * to index 0. This null case is split out into separate methods 429 * for the sake of performance in the two most commonly used 430 * operations (get and put), but incorporated with conditionals in 431 * others. 432 */ 433 private V getForNullKey() { 434 if (size == 0) { 435 return null; 436 } 437 for (Entry<K,V> e = table[0]; e != null; e = e.next) { 438 if (e.key == null) 439 return e.value; 440 } 441 return null; 442 } 443 444 /** 445 * Returns <tt>true</tt> if this map contains a mapping for the 446 * specified key. 447 * 448 * @param key The key whose presence in this map is to be tested 449 * @return <tt>true</tt> if this map contains a mapping for the specified 450 * key. 451 */ 452 public boolean containsKey(Object key) { 453 return getEntry(key) != null; 454 } 455 456 /** 457 * Returns the entry associated with the specified key in the 458 * HashMap. Returns null if the HashMap contains no mapping 459 * for the key. 460 */ 461 final Entry<K,V> getEntry(Object key) { 462 if (size == 0) { 463 return null; 464 } 465 466 int hash = (key == null) ? 0 : hash(key); 467 for (Entry<K,V> e = table[indexFor(hash, table.length)]; 468 e != null; 469 e = e.next) { 470 Object k; 471 if (e.hash == hash && 472 ((k = e.key) == key || (key != null && key.equals(k)))) 473 return e; 474 } 475 return null; 476 } 477 478 /** 479 * Associates the specified value with the specified key in this map. 480 * If the map previously contained a mapping for the key, the old 481 * value is replaced. 482 * 483 * @param key key with which the specified value is to be associated 484 * @param value value to be associated with the specified key 485 * @return the previous value associated with <tt>key</tt>, or 486 * <tt>null</tt> if there was no mapping for <tt>key</tt>. 487 * (A <tt>null</tt> return can also indicate that the map 488 * previously associated <tt>null</tt> with <tt>key</tt>.) 489 */ 490 public V put(K key, V value) { 491 if (table == EMPTY_TABLE) { 492 inflateTable(threshold); 493 } 494 if (key == null) 495 return putForNullKey(value); 496 int hash = hash(key); 497 int i = indexFor(hash, table.length); 498 for (Entry<K,V> e = table[i]; e != null; e = e.next) { 499 Object k; 500 if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { 501 V oldValue = e.value; 502 e.value = value; 503 e.recordAccess(this); 504 return oldValue; 505 } 506 } 507 508 modCount++; 509 addEntry(hash, key, value, i); 510 return null; 511 } 512 513 /** 514 * Offloaded version of put for null keys 515 */ 516 private V putForNullKey(V value) { 517 for (Entry<K,V> e = table[0]; e != null; e = e.next) { 518 if (e.key == null) { 519 V oldValue = e.value; 520 e.value = value; 521 e.recordAccess(this); 522 return oldValue; 523 } 524 } 525 modCount++; 526 addEntry(0, null, value, 0); 527 return null; 528 } 529 530 /** 531 * This method is used instead of put by constructors and 532 * pseudoconstructors (clone, readObject). It does not resize the table, 533 * check for comodification, etc. It calls createEntry rather than 534 * addEntry. 535 */ 536 private void putForCreate(K key, V value) { 537 int hash = null == key ? 0 : hash(key); 538 int i = indexFor(hash, table.length); 539 540 /** 541 * Look for preexisting entry for key. This will never happen for 542 * clone or deserialize. It will only happen for construction if the 543 * input Map is a sorted map whose ordering is inconsistent w/ equals. 544 */ 545 for (Entry<K,V> e = table[i]; e != null; e = e.next) { 546 Object k; 547 if (e.hash == hash && 548 ((k = e.key) == key || (key != null && key.equals(k)))) { 549 e.value = value; 550 return; 551 } 552 } 553 554 createEntry(hash, key, value, i); 555 } 556 557 private void putAllForCreate(Map<? extends K, ? extends V> m) { 558 for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) 559 putForCreate(e.getKey(), e.getValue()); 560 } 561 562 /** 563 * Rehashes the contents of this map into a new array with a 564 * larger capacity. This method is called automatically when the 565 * number of keys in this map reaches its threshold. 566 * 567 * If current capacity is MAXIMUM_CAPACITY, this method does not 568 * resize the map, but sets threshold to Integer.MAX_VALUE. 569 * This has the effect of preventing future calls. 570 * 571 * @param newCapacity the new capacity, MUST be a power of two; 572 * must be greater than current capacity unless current 573 * capacity is MAXIMUM_CAPACITY (in which case value 574 * is irrelevant). 575 */ 576 void resize(int newCapacity) { 577 Entry[] oldTable = table; 578 int oldCapacity = oldTable.length; 579 if (oldCapacity == MAXIMUM_CAPACITY) { 580 threshold = Integer.MAX_VALUE; 581 return; 582 } 583 584 Entry[] newTable = new Entry[newCapacity]; 585 transfer(newTable, initHashSeedAsNeeded(newCapacity)); 586 table = newTable; 587 threshold = (int)Math.min(newCapacity * loadFactor, MAXIMUM_CAPACITY + 1); 588 } 589 590 /** 591 * Transfers all entries from current table to newTable. 592 */ 593 void transfer(Entry[] newTable, boolean rehash) { 594 int newCapacity = newTable.length; 595 for (Entry<K,V> e : table) { 596 while(null != e) { 597 Entry<K,V> next = e.next; 598 if (rehash) { 599 e.hash = null == e.key ? 0 : hash(e.key); 600 } 601 int i = indexFor(e.hash, newCapacity); 602 e.next = newTable[i]; 603 newTable[i] = e; 604 e = next; 605 } 606 } 607 } 608 609 /** 610 * Copies all of the mappings from the specified map to this map. 611 * These mappings will replace any mappings that this map had for 612 * any of the keys currently in the specified map. 613 * 614 * @param m mappings to be stored in this map 615 * @throws NullPointerException if the specified map is null 616 */ 617 public void putAll(Map<? extends K, ? extends V> m) { 618 int numKeysToBeAdded = m.size(); 619 if (numKeysToBeAdded == 0) 620 return; 621 622 if (table == EMPTY_TABLE) { 623 inflateTable((int) Math.max(numKeysToBeAdded * loadFactor, threshold)); 624 } 625 626 /* 627 * Expand the map if the map if the number of mappings to be added 628 * is greater than or equal to threshold. This is conservative; the 629 * obvious condition is (m.size() + size) >= threshold, but this 630 * condition could result in a map with twice the appropriate capacity, 631 * if the keys to be added overlap with the keys already in this map. 632 * By using the conservative calculation, we subject ourself 633 * to at most one extra resize. 634 */ 635 if (numKeysToBeAdded > threshold) { 636 int targetCapacity = (int)(numKeysToBeAdded / loadFactor + 1); 637 if (targetCapacity > MAXIMUM_CAPACITY) 638 targetCapacity = MAXIMUM_CAPACITY; 639 int newCapacity = table.length; 640 while (newCapacity < targetCapacity) 641 newCapacity <<= 1; 642 if (newCapacity > table.length) 643 resize(newCapacity); 644 } 645 646 for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) 647 put(e.getKey(), e.getValue()); 648 } 649 650 /** 651 * Removes the mapping for the specified key from this map if present. 652 * 653 * @param key key whose mapping is to be removed from the map 654 * @return the previous value associated with <tt>key</tt>, or 655 * <tt>null</tt> if there was no mapping for <tt>key</tt>. 656 * (A <tt>null</tt> return can also indicate that the map 657 * previously associated <tt>null</tt> with <tt>key</tt>.) 658 */ 659 public V remove(Object key) { 660 Entry<K,V> e = removeEntryForKey(key); 661 return (e == null ? null : e.value); 662 } 663 664 /** 665 * Removes and returns the entry associated with the specified key 666 * in the HashMap. Returns null if the HashMap contains no mapping 667 * for this key. 668 */ 669 final Entry<K,V> removeEntryForKey(Object key) { 670 if (size == 0) { 671 return null; 672 } 673 int hash = (key == null) ? 0 : hash(key); 674 int i = indexFor(hash, table.length); 675 Entry<K,V> prev = table[i]; 676 Entry<K,V> e = prev; 677 678 while (e != null) { 679 Entry<K,V> next = e.next; 680 Object k; 681 if (e.hash == hash && 682 ((k = e.key) == key || (key != null && key.equals(k)))) { 683 modCount++; 684 size--; 685 if (prev == e) 686 table[i] = next; 687 else 688 prev.next = next; 689 e.recordRemoval(this); 690 return e; 691 } 692 prev = e; 693 e = next; 694 } 695 696 return e; 697 } 698 699 /** 700 * Special version of remove for EntrySet using {@code Map.Entry.equals()} 701 * for matching. 702 */ 703 final Entry<K,V> removeMapping(Object o) { 704 if (size == 0 || !(o instanceof Map.Entry)) 705 return null; 706 707 Map.Entry<K,V> entry = (Map.Entry<K,V>) o; 708 Object key = entry.getKey(); 709 int hash = (key == null) ? 0 : hash(key); 710 int i = indexFor(hash, table.length); 711 Entry<K,V> prev = table[i]; 712 Entry<K,V> e = prev; 713 714 while (e != null) { 715 Entry<K,V> next = e.next; 716 if (e.hash == hash && e.equals(entry)) { 717 modCount++; 718 size--; 719 if (prev == e) 720 table[i] = next; 721 else 722 prev.next = next; 723 e.recordRemoval(this); 724 return e; 725 } 726 prev = e; 727 e = next; 728 } 729 730 return e; 731 } 732 733 /** 734 * Removes all of the mappings from this map. 735 * The map will be empty after this call returns. 736 */ 737 public void clear() { 738 modCount++; 739 Arrays.fill(table, null); 740 size = 0; 741 } 742 743 /** 744 * Returns <tt>true</tt> if this map maps one or more keys to the 745 * specified value. 746 * 747 * @param value value whose presence in this map is to be tested 748 * @return <tt>true</tt> if this map maps one or more keys to the 749 * specified value 750 */ 751 public boolean containsValue(Object value) { 752 if (value == null) 753 return containsNullValue(); 754 755 Entry[] tab = table; 756 for (int i = 0; i < tab.length ; i++) 757 for (Entry e = tab[i] ; e != null ; e = e.next) 758 if (value.equals(e.value)) 759 return true; 760 return false; 761 } 762 763 /** 764 * Special-case code for containsValue with null argument 765 */ 766 private boolean containsNullValue() { 767 Entry[] tab = table; 768 for (int i = 0; i < tab.length ; i++) 769 for (Entry e = tab[i] ; e != null ; e = e.next) 770 if (e.value == null) 771 return true; 772 return false; 773 } 774 775 /** 776 * Returns a shallow copy of this <tt>HashMap</tt> instance: the keys and 777 * values themselves are not cloned. 778 * 779 * @return a shallow copy of this map 780 */ 781 public Object clone() { 782 HashMap<K,V> result = null; 783 try { 784 result = (HashMap<K,V>)super.clone(); 785 } catch (CloneNotSupportedException e) { 786 // assert false; 787 } 788 if (result.table != EMPTY_TABLE) { 789 result.inflateTable(Math.min( 790 (int) Math.min( 791 size * Math.min(1 / loadFactor, 4.0f), 792 // we have limits... 793 HashMap.MAXIMUM_CAPACITY), 794 table.length)); 795 } 796 result.entrySet = null; 797 result.modCount = 0; 798 result.size = 0; 799 result.init(); 800 result.putAllForCreate(this); 801 802 return result; 803 } 804 805 static class Entry<K,V> implements Map.Entry<K,V> { 806 final K key; 807 V value; 808 Entry<K,V> next; 809 int hash; 810 811 /** 812 * Creates new entry. 813 */ 814 Entry(int h, K k, V v, Entry<K,V> n) { 815 value = v; 816 next = n; 817 key = k; 818 hash = h; 819 } 820 821 public final K getKey() { 822 return key; 823 } 824 825 public final V getValue() { 826 return value; 827 } 828 829 public final V setValue(V newValue) { 830 V oldValue = value; 831 value = newValue; 832 return oldValue; 833 } 834 835 public final boolean equals(Object o) { 836 if (!(o instanceof Map.Entry)) 837 return false; 838 Map.Entry e = (Map.Entry)o; 839 Object k1 = getKey(); 840 Object k2 = e.getKey(); 841 if (k1 == k2 || (k1 != null && k1.equals(k2))) { 842 Object v1 = getValue(); 843 Object v2 = e.getValue(); 844 if (v1 == v2 || (v1 != null && v1.equals(v2))) 845 return true; 846 } 847 return false; 848 } 849 850 public final int hashCode() { 851 return Objects.hashCode(getKey()) ^ Objects.hashCode(getValue()); 852 } 853 854 public final String toString() { 855 return getKey() + "=" + getValue(); 856 } 857 858 /** 859 * This method is invoked whenever the value in an entry is 860 * overwritten by an invocation of put(k,v) for a key k that's already 861 * in the HashMap. 862 */ 863 void recordAccess(HashMap<K,V> m) { 864 } 865 866 /** 867 * This method is invoked whenever the entry is 868 * removed from the table. 869 */ 870 void recordRemoval(HashMap<K,V> m) { 871 } 872 } 873 874 /** 875 * Adds a new entry with the specified key, value and hash code to 876 * the specified bucket. It is the responsibility of this 877 * method to resize the table if appropriate. 878 * 879 * Subclass overrides this to alter the behavior of put method. 880 */ 881 void addEntry(int hash, K key, V value, int bucketIndex) { 882 if ((size >= threshold) && (null != table[bucketIndex])) { 883 resize(2 * table.length); 884 hash = (null != key) ? hash(key) : 0; 885 bucketIndex = indexFor(hash, table.length); 886 } 887 888 createEntry(hash, key, value, bucketIndex); 889 } 890 891 /** 892 * Like addEntry except that this version is used when creating entries 893 * as part of Map construction or "pseudo-construction" (cloning, 894 * deserialization). This version needn't worry about resizing the table. 895 * 896 * Subclass overrides this to alter the behavior of HashMap(Map), 897 * clone, and readObject. 898 */ 899 void createEntry(int hash, K key, V value, int bucketIndex) { 900 Entry<K,V> e = table[bucketIndex]; 901 table[bucketIndex] = new Entry<>(hash, key, value, e); 902 size++; 903 } 904 905 private abstract class HashIterator<E> implements Iterator<E> { 906 Entry<K,V> next; // next entry to return 907 int expectedModCount; // For fast-fail 908 int index; // current slot 909 Entry<K,V> current; // current entry 910 911 HashIterator() { 912 expectedModCount = modCount; 913 if (size > 0) { // advance to first entry 914 Entry[] t = table; 915 while (index < t.length && (next = t[index++]) == null) 916 ; 917 } 918 } 919 920 public final boolean hasNext() { 921 return next != null; 922 } 923 924 final Entry<K,V> nextEntry() { 925 if (modCount != expectedModCount) 926 throw new ConcurrentModificationException(); 927 Entry<K,V> e = next; 928 if (e == null) 929 throw new NoSuchElementException(); 930 931 if ((next = e.next) == null) { 932 Entry[] t = table; 933 while (index < t.length && (next = t[index++]) == null) 934 ; 935 } 936 current = e; 937 return e; 938 } 939 940 public void remove() { 941 if (current == null) 942 throw new IllegalStateException(); 943 if (modCount != expectedModCount) 944 throw new ConcurrentModificationException(); 945 Object k = current.key; 946 current = null; 947 HashMap.this.removeEntryForKey(k); 948 expectedModCount = modCount; 949 } 950 } 951 952 private final class ValueIterator extends HashIterator<V> { 953 public V next() { 954 return nextEntry().value; 955 } 956 } 957 958 private final class KeyIterator extends HashIterator<K> { 959 public K next() { 960 return nextEntry().getKey(); 961 } 962 } 963 964 private final class EntryIterator extends HashIterator<Map.Entry<K,V>> { 965 public Map.Entry<K,V> next() { 966 return nextEntry(); 967 } 968 } 969 970 // Subclass overrides these to alter behavior of views' iterator() method 971 Iterator<K> newKeyIterator() { 972 return new KeyIterator(); 973 } 974 Iterator<V> newValueIterator() { 975 return new ValueIterator(); 976 } 977 Iterator<Map.Entry<K,V>> newEntryIterator() { 978 return new EntryIterator(); 979 } 980 981 982 // Views 983 984 private transient Set<Map.Entry<K,V>> entrySet = null; 985 986 /** 987 * Returns a {@link Set} view of the keys contained in this map. 988 * The set is backed by the map, so changes to the map are 989 * reflected in the set, and vice-versa. If the map is modified 990 * while an iteration over the set is in progress (except through 991 * the iterator's own <tt>remove</tt> operation), the results of 992 * the iteration are undefined. The set supports element removal, 993 * which removes the corresponding mapping from the map, via the 994 * <tt>Iterator.remove</tt>, <tt>Set.remove</tt>, 995 * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt> 996 * operations. It does not support the <tt>add</tt> or <tt>addAll</tt> 997 * operations. 998 */ 999 public Set<K> keySet() { 1000 Set<K> ks = keySet; 1001 return (ks != null ? ks : (keySet = new KeySet())); 1002 } 1003 1004 private final class KeySet extends AbstractSet<K> { 1005 public Iterator<K> iterator() { 1006 return newKeyIterator(); 1007 } 1008 public int size() { 1009 return size; 1010 } 1011 public boolean contains(Object o) { 1012 return containsKey(o); 1013 } 1014 public boolean remove(Object o) { 1015 return HashMap.this.removeEntryForKey(o) != null; 1016 } 1017 public void clear() { 1018 HashMap.this.clear(); 1019 } 1020 } 1021 1022 /** 1023 * Returns a {@link Collection} view of the values contained in this map. 1024 * The collection is backed by the map, so changes to the map are 1025 * reflected in the collection, and vice-versa. If the map is 1026 * modified while an iteration over the collection is in progress 1027 * (except through the iterator's own <tt>remove</tt> operation), 1028 * the results of the iteration are undefined. The collection 1029 * supports element removal, which removes the corresponding 1030 * mapping from the map, via the <tt>Iterator.remove</tt>, 1031 * <tt>Collection.remove</tt>, <tt>removeAll</tt>, 1032 * <tt>retainAll</tt> and <tt>clear</tt> operations. It does not 1033 * support the <tt>add</tt> or <tt>addAll</tt> operations. 1034 */ 1035 public Collection<V> values() { 1036 Collection<V> vs = values; 1037 return (vs != null ? vs : (values = new Values())); 1038 } 1039 1040 private final class Values extends AbstractCollection<V> { 1041 public Iterator<V> iterator() { 1042 return newValueIterator(); 1043 } 1044 public int size() { 1045 return size; 1046 } 1047 public boolean contains(Object o) { 1048 return containsValue(o); 1049 } 1050 public void clear() { 1051 HashMap.this.clear(); 1052 } 1053 } 1054 1055 /** 1056 * Returns a {@link Set} view of the mappings contained in this map. 1057 * The set is backed by the map, so changes to the map are 1058 * reflected in the set, and vice-versa. If the map is modified 1059 * while an iteration over the set is in progress (except through 1060 * the iterator's own <tt>remove</tt> operation, or through the 1061 * <tt>setValue</tt> operation on a map entry returned by the 1062 * iterator) the results of the iteration are undefined. The set 1063 * supports element removal, which removes the corresponding 1064 * mapping from the map, via the <tt>Iterator.remove</tt>, 1065 * <tt>Set.remove</tt>, <tt>removeAll</tt>, <tt>retainAll</tt> and 1066 * <tt>clear</tt> operations. It does not support the 1067 * <tt>add</tt> or <tt>addAll</tt> operations. 1068 * 1069 * @return a set view of the mappings contained in this map 1070 */ 1071 public Set<Map.Entry<K,V>> entrySet() { 1072 return entrySet0(); 1073 } 1074 1075 private Set<Map.Entry<K,V>> entrySet0() { 1076 Set<Map.Entry<K,V>> es = entrySet; 1077 return es != null ? es : (entrySet = new EntrySet()); 1078 } 1079 1080 private final class EntrySet extends AbstractSet<Map.Entry<K,V>> { 1081 public Iterator<Map.Entry<K,V>> iterator() { 1082 return newEntryIterator(); 1083 } 1084 public boolean contains(Object o) { 1085 if (!(o instanceof Map.Entry)) 1086 return false; 1087 Map.Entry<K,V> e = (Map.Entry<K,V>) o; 1088 Entry<K,V> candidate = getEntry(e.getKey()); 1089 return candidate != null && candidate.equals(e); 1090 } 1091 public boolean remove(Object o) { 1092 return removeMapping(o) != null; 1093 } 1094 public int size() { 1095 return size; 1096 } 1097 public void clear() { 1098 HashMap.this.clear(); 1099 } 1100 } 1101 1102 /** 1103 * Save the state of the <tt>HashMap</tt> instance to a stream (i.e., 1104 * serialize it). 1105 * 1106 * @serialData The <i>capacity</i> of the HashMap (the length of the 1107 * bucket array) is emitted (int), followed by the 1108 * <i>size</i> (an int, the number of key-value 1109 * mappings), followed by the key (Object) and value (Object) 1110 * for each key-value mapping. The key-value mappings are 1111 * emitted in no particular order. 1112 */ 1113 private void writeObject(java.io.ObjectOutputStream s) 1114 throws IOException 1115 { 1116 // Write out the threshold, loadfactor, and any hidden stuff 1117 s.defaultWriteObject(); 1118 1119 // Write out number of buckets 1120 if (table==EMPTY_TABLE) { 1121 s.writeInt(roundUpToPowerOf2(threshold)); 1122 } else { 1123 s.writeInt(table.length); 1124 } 1125 1126 // Write out size (number of Mappings) 1127 s.writeInt(size); 1128 1129 // Write out keys and values (alternating) 1130 if (size > 0) { 1131 for(Map.Entry<K,V> e : entrySet0()) { 1132 s.writeObject(e.getKey()); 1133 s.writeObject(e.getValue()); 1134 } 1135 } 1136 } 1137 1138 private static final long serialVersionUID = 362498820763181265L; 1139 1140 /** 1141 * Reconstitute the {@code HashMap} instance from a stream (i.e., 1142 * deserialize it). 1143 */ 1144 private void readObject(java.io.ObjectInputStream s) 1145 throws IOException, ClassNotFoundException 1146 { 1147 // Read in the threshold (ignored), loadfactor, and any hidden stuff 1148 s.defaultReadObject(); 1149 if (loadFactor <= 0 || Float.isNaN(loadFactor)) { 1150 throw new InvalidObjectException("Illegal load factor: " + 1151 loadFactor); 1152 } 1153 1154 // set other fields that need values 1155 table = (Entry<K,V>[]) EMPTY_TABLE; 1156 1157 // Read in number of buckets 1158 s.readInt(); // ignored. 1159 1160 // Read number of mappings 1161 int mappings = s.readInt(); 1162 if (mappings < 0) 1163 throw new InvalidObjectException("Illegal mappings count: " + 1164 mappings); 1165 1166 // capacity chosen by number of mappings and desired load (if >= 0.25) 1167 int capacity = (int) Math.min( 1168 mappings * Math.min(1 / loadFactor, 4.0f), 1169 // we have limits... 1170 HashMap.MAXIMUM_CAPACITY); 1171 1172 // allocate the bucket array; 1173 if (mappings > 0) { 1174 inflateTable(capacity); 1175 } else { 1176 threshold = capacity; 1177 } 1178 1179 init(); // Give subclass a chance to do its thing. 1180 1181 // Read the keys and values, and put the mappings in the HashMap 1182 for (int i = 0; i < mappings; i++) { 1183 K key = (K) s.readObject(); 1184 V value = (V) s.readObject(); 1185 putForCreate(key, value); 1186 } 1187 } 1188 1189 // These methods are used when serializing HashSets 1190 int capacity() { return table.length; } 1191 float loadFactor() { return loadFactor; } 1192 }
1 /* 2 * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. 3 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13 * 14 * 15 * 16 * 17 * 18 * 19 * 20 * 21 * 22 * 23 * 24 */ 25 26 package java.util; 27 import java.io.*; 28 29 /** 30 * Hash table based implementation of the <tt>Map</tt> interface. This 31 * implementation provides all of the optional map operations, and permits 32 * <tt>null</tt> values and the <tt>null</tt> key. (The <tt>HashMap</tt> 33 * class is roughly(粗糙地;概略地) equivalent(相等的,相当的) to <tt>Hashtable</tt>, except that it is 34 * unsynchronized(非同步的) and permits nulls.) This class makes no guarantees as to 35 * the order of the map; in particular(尤其,特别), it does not guarantee(保证) that the order 36 * will remain constant over time. 37 * 38 * <p>This implementation provides constant-time performance for the basic 39 * operations (<tt>get</tt> and <tt>put</tt>), assuming the hash function 40 * disperses(散开,驱散) the elements properly among the buckets(桶). Iteration over 41 * collection views requires time proportional to the "capacity" of the 42 * <tt>HashMap</tt> instance (the number of buckets) plus its size (the number 43 * of key-value mappings). Thus, it's very important not to set the initial 44 * capacity too high (or the load factor too low) if iteration performance is 45 * important. 46 * 47 * <p>An instance(例子,实例) of <tt>HashMap</tt> has two parameters that affect its 48 * performance: <i>initial capacity</i> and <i>load factor</i>. The 49 * <i>capacity</i> is the number of buckets in the hash table, and the initial 50 * capacity is simply the capacity at the time the hash table is created. The 51 * <i>load factor</i> is a measure of how full the hash table is allowed to 52 * get before its capacity is automatically increased. When the number of 53 * entries in the hash table exceeds(超过;超越) the product of the load factor and the 54 * current capacity, the hash table is <i>rehashed</i> (that is, internal data 55 * structures are rebuilt) so that the hash table has approximately(近似地,大约) twice the 56 * number of buckets. 57 * 58 * <p>As a general rule, the default load factor (.75) offers a good tradeoff(权衡,折中) 59 * between time and space costs. Higher values decrease the space overhead 60 * but increase the lookup cost (reflected in most of the operations of the 61 * <tt>HashMap</tt> class, including <tt>get</tt> and <tt>put</tt>). The 62 * expected number of entries in the map and its load factor should be taken 63 * into account when setting its initial capacity, so as to minimize the 64 * number of rehash operations. If the initial capacity is greater 65 * than the maximum number of entries divided by the load factor, no 66 * rehash operations will ever occur. 67 * 68 * <p>If many mappings are to be stored in a <tt>HashMap</tt> instance, 69 * creating it with a sufficiently large capacity will allow the mappings to 70 * be stored more efficiently than letting it perform automatic rehashing as 71 * needed to grow the table. 72 * 73 * <p><strong>Note that this implementation is not synchronized.</strong> 74 * If multiple threads access a hash map concurrently, and at least one of 75 * the threads modifies the map structurally, it <i>must</i> be 76 * synchronized externally. (A structural modification is any operation 77 * that adds or deletes one or more mappings; merely changing the value 78 * associated with a key that an instance already contains is not a 79 * structural modification.) This is typically accomplished by 80 * synchronizing on some object that naturally encapsulates(总结;扼要概括) the map. 81 * 82 * If no such object exists, the map should be "wrapped" using the 83 * {@link Collections#synchronizedMap Collections.synchronizedMap} 84 * method. This is best done at creation time, to prevent accidental 85 * unsynchronized access to the map:<pre> 86 * Map m = Collections.synchronizedMap(new HashMap(...));</pre> 87 * 88 * <p>The iterators returned by all of this class's "collection view methods" 89 * are <i>fail-fast</i>: if the map is structurally modified at any time after 90 * the iterator is created, in any way except through the iterator's own 91 * <tt>remove</tt> method, the iterator will throw a 92 * {@link ConcurrentModificationException}. Thus, in the face of concurrent 93 * modification, the iterator fails quickly and cleanly, rather than risking 94 * arbitrary, non-deterministic behavior at an undetermined time in the 95 * future. 96 * 97 * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed 98 * as it is, generally speaking, impossible to make any hard guarantees in the 99 * presence of unsynchronized concurrent modification. Fail-fast iterators 100 * throw <tt>ConcurrentModificationException</tt> on a best-effort basis. 101 * Therefore, it would be wrong to write a program that depended on this 102 * exception for its correctness: <i>the fail-fast behavior of iterators 103 * should be used only to detect bugs.</i> 104 * 105 * <p>This class is a member of the 106 * <a href="{@docRoot}/../technotes/guides/collections/index.html"> 107 * Java Collections Framework</a>. 108 * 109 * @param <K> the type of keys maintained by this map 110 * @param <V> the type of mapped values 111 * 112 * @author Doug Lea 113 * @author Josh Bloch 114 * @author Arthur van Hoff 115 * @author Neal Gafter 116 * @see Object#hashCode() 117 * @see Collection 118 * @see Map 119 * @see TreeMap 120 * @see Hashtable 121 * @since 1.2 122 */ 123 124 public class HashMap<K,V> 125 extends AbstractMap<K,V> 126 implements Map<K,V>, Cloneable, Serializable 127 { 128 129 /** 130 * The default initial capacity - MUST be a power of two. 131 */ 132 static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16 133 134 /** 135 * The maximum capacity, used if a higher value is implicitly specified 136 * by either of the constructors with arguments. 137 * MUST be a power of two <= 1<<30. 138 */ 139 static final int MAXIMUM_CAPACITY = 1 << 30; 140 141 /** 142 * The load factor used when none specified in constructor. 143 */ 144 static final float DEFAULT_LOAD_FACTOR = 0.75f; 145 146 /** 147 * An empty table instance to share when the table is not inflated. 148 */ 149 static final Entry<?,?>[] EMPTY_TABLE = {}; 150 151 /** 152 * The table, resized as necessary. Length MUST Always be a power of two. 153 */ 154 transient Entry<K,V>[] table = (Entry<K,V>[]) EMPTY_TABLE; 155 156 /** 157 * The number of key-value mappings contained in this map. 158 */ 159 transient int size; 160 161 /** 162 * The next size value at which to resize (capacity * load factor). 163 * @serial 164 */ 165 // If table == EMPTY_TABLE then this is the initial capacity at which the 166 // table will be created when inflated. 167 int threshold; 168 169 /** 170 * The load factor for the hash table. 171 * 172 * @serial 173 */ 174 final float loadFactor; 175 176 /** 177 * The number of times this HashMap has been structurally modified 178 * Structural modifications are those that change the number of mappings in 179 * the HashMap or otherwise modify its internal structure (e.g., 180 * rehash). This field is used to make iterators on Collection-views of 181 * the HashMap fail-fast. (See ConcurrentModificationException). 182 */ 183 transient int modCount; 184 185 /** 186 * The default threshold of map capacity above which alternative hashing is 187 * used for String keys. Alternative hashing reduces the incidence of 188 * collisions due to weak hash code calculation for String keys. 189 * <p/> 190 * This value may be overridden by defining the system property 191 * {@code jdk.map.althashing.threshold}. A property value of {@code 1} 192 * forces alternative hashing to be used at all times whereas 193 * {@code -1} value ensures that alternative hashing is never used. 194 */ 195 static final int ALTERNATIVE_HASHING_THRESHOLD_DEFAULT = Integer.MAX_VALUE; 196 197 /** 198 * holds values which can't be initialized until after VM is booted. 199 */ 200 private static class Holder { 201 202 /** 203 * Table capacity above which to switch to use alternative hashing. 204 */ 205 static final int ALTERNATIVE_HASHING_THRESHOLD; 206 207 static { 208 String altThreshold = java.security.AccessController.doPrivileged( 209 new sun.security.action.GetPropertyAction( 210 "jdk.map.althashing.threshold")); 211 212 int threshold; 213 try { 214 threshold = (null != altThreshold) 215 ? Integer.parseInt(altThreshold) 216 : ALTERNATIVE_HASHING_THRESHOLD_DEFAULT; 217 218 // disable alternative hashing if -1 219 if (threshold == -1) { 220 threshold = Integer.MAX_VALUE; 221 } 222 223 if (threshold < 0) { 224 throw new IllegalArgumentException("value must be positive integer."); 225 } 226 } catch(IllegalArgumentException failed) { 227 throw new Error("Illegal value for 'jdk.map.althashing.threshold'", failed); 228 } 229 230 ALTERNATIVE_HASHING_THRESHOLD = threshold; 231 } 232 } 233 234 /** 235 * A randomizing value associated with this instance that is applied to 236 * hash code of keys to make hash collisions harder to find. If 0 then 237 * alternative hashing is disabled. 238 */ 239 transient int hashSeed = 0; 240 241 /** 242 * Constructs an empty <tt>HashMap</tt> with the specified initial 243 * capacity and load factor. 244 * 245 * @param initialCapacity the initial capacity 246 * @param loadFactor the load factor 247 * @throws IllegalArgumentException if the initial capacity is negative 248 * or the load factor is nonpositive 249 */ 250 public HashMap(int initialCapacity, float loadFactor) { 251 if (initialCapacity < 0) 252 throw new IllegalArgumentException("Illegal initial capacity: " + 253 initialCapacity); 254 if (initialCapacity > MAXIMUM_CAPACITY) 255 initialCapacity = MAXIMUM_CAPACITY; 256 if (loadFactor <= 0 || Float.isNaN(loadFactor)) 257 throw new IllegalArgumentException("Illegal load factor: " + 258 loadFactor); 259 260 this.loadFactor = loadFactor; 261 threshold = initialCapacity; 262 init(); 263 } 264 265 /** 266 * Constructs an empty <tt>HashMap</tt> with the specified initial 267 * capacity and the default load factor (0.75). 268 * 269 * @param initialCapacity the initial capacity. 270 * @throws IllegalArgumentException if the initial capacity is negative. 271 */ 272 public HashMap(int initialCapacity) { 273 this(initialCapacity, DEFAULT_LOAD_FACTOR); 274 } 275 276 /** 277 * Constructs an empty <tt>HashMap</tt> with the default initial capacity 278 * (16) and the default load factor (0.75). 279 */ 280 public HashMap() { 281 this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR); 282 } 283 284 /** 285 * Constructs a new <tt>HashMap</tt> with the same mappings as the 286 * specified <tt>Map</tt>. The <tt>HashMap</tt> is created with 287 * default load factor (0.75) and an initial capacity sufficient to 288 * hold the mappings in the specified <tt>Map</tt>. 289 * 290 * @param m the map whose mappings are to be placed in this map 291 * @throws NullPointerException if the specified map is null 292 */ 293 public HashMap(Map<? extends K, ? extends V> m) { 294 this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1, 295 DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR); 296 inflateTable(threshold); 297 298 putAllForCreate(m); 299 } 300 301 private static int roundUpToPowerOf2(int number) { 302 // assert number >= 0 : "number must be non-negative"; 303 int rounded = number >= MAXIMUM_CAPACITY 304 ? MAXIMUM_CAPACITY 305 : (rounded = Integer.highestOneBit(number)) != 0 306 ? (Integer.bitCount(number) > 1) ? rounded << 1 : rounded 307 : 1; 308 309 return rounded; 310 } 311 312 /** 313 * Inflates the table. 314 */ 315 private void inflateTable(int toSize) { 316 // Find a power of 2 >= toSize 317 int capacity = roundUpToPowerOf2(toSize); 318 319 threshold = (int) Math.min(capacity * loadFactor, MAXIMUM_CAPACITY + 1); 320 table = new Entry[capacity]; 321 initHashSeedAsNeeded(capacity); 322 } 323 324 // internal utilities 325 326 /** 327 * Initialization hook for subclasses. This method is called 328 * in all constructors and pseudo-constructors (clone, readObject) 329 * after HashMap has been initialized but before any entries have 330 * been inserted. (In the absence of this method, readObject would 331 * require explicit knowledge of subclasses.) 332 */ 333 void init() { 334 } 335 336 /** 337 * Initialize the hashing mask value. We defer initialization until we 338 * really need it. 339 */ 340 final boolean initHashSeedAsNeeded(int capacity) { 341 boolean currentAltHashing = hashSeed != 0; 342 boolean useAltHashing = sun.misc.VM.isBooted() && 343 (capacity >= Holder.ALTERNATIVE_HASHING_THRESHOLD); 344 boolean switching = currentAltHashing ^ useAltHashing; 345 if (switching) { 346 hashSeed = useAltHashing 347 ? sun.misc.Hashing.randomHashSeed(this) 348 : 0; 349 } 350 return switching; 351 } 352 353 /** 354 * Retrieve object hash code and applies a supplemental hash function to the 355 * result hash, which defends against poor quality hash functions. This is 356 * critical because HashMap uses power-of-two length hash tables, that 357 * otherwise encounter collisions for hashCodes that do not differ 358 * in lower bits. Note: Null keys always map to hash 0, thus index 0. 359 */ 360 final int hash(Object k) { 361 int h = hashSeed; 362 if (0 != h && k instanceof String) { 363 return sun.misc.Hashing.stringHash32((String) k); 364 } 365 366 h ^= k.hashCode(); 367 368 // This function ensures that hashCodes that differ only by 369 // constant multiples at each bit position have a bounded 370 // number of collisions (approximately 8 at default load factor). 371 h ^= (h >>> 20) ^ (h >>> 12); 372 return h ^ (h >>> 7) ^ (h >>> 4); 373 } 374 375 /** 376 * Returns index for hash code h. 377 */ 378 static int indexFor(int h, int length) { 379 // assert Integer.bitCount(length) == 1 : "length must be a non-zero power of 2"; 380 return h & (length-1); 381 } 382 383 /** 384 * Returns the number of key-value mappings in this map. 385 * 386 * @return the number of key-value mappings in this map 387 */ 388 public int size() { 389 return size; 390 } 391 392 /** 393 * Returns <tt>true</tt> if this map contains no key-value mappings. 394 * 395 * @return <tt>true</tt> if this map contains no key-value mappings 396 */ 397 public boolean isEmpty() { 398 return size == 0; 399 } 400 401 /** 402 * Returns the value to which the specified key is mapped, 403 * or {@code null} if this map contains no mapping for the key. 404 * 405 * <p>More formally, if this map contains a mapping from a key 406 * {@code k} to a value {@code v} such that {@code (key==null ? k==null : 407 * key.equals(k))}, then this method returns {@code v}; otherwise 408 * it returns {@code null}. (There can be at most one such mapping.) 409 * 410 * <p>A return value of {@code null} does not <i>necessarily</i> 411 * indicate that the map contains no mapping for the key; it's also 412 * possible that the map explicitly maps the key to {@code null}. 413 * The {@link #containsKey containsKey} operation may be used to 414 * distinguish these two cases. 415 * 416 * @see #put(Object, Object) 417 */ 418 public V get(Object key) { 419 if (key == null) 420 return getForNullKey(); 421 Entry<K,V> entry = getEntry(key); 422 423 return null == entry ? null : entry.getValue(); 424 } 425 426 /** 427 * Offloaded version of get() to look up null keys. Null keys map 428 * to index 0. This null case is split out into separate methods 429 * for the sake of performance in the two most commonly used 430 * operations (get and put), but incorporated with conditionals in 431 * others. 432 */ 433 private V getForNullKey() { 434 if (size == 0) { 435 return null; 436 } 437 for (Entry<K,V> e = table[0]; e != null; e = e.next) { 438 if (e.key == null) 439 return e.value; 440 } 441 return null; 442 } 443 444 /** 445 * Returns <tt>true</tt> if this map contains a mapping for the 446 * specified key. 447 * 448 * @param key The key whose presence in this map is to be tested 449 * @return <tt>true</tt> if this map contains a mapping for the specified 450 * key. 451 */ 452 public boolean containsKey(Object key) { 453 return getEntry(key) != null; 454 } 455 456 /** 457 * Returns the entry associated with the specified key in the 458 * HashMap. Returns null if the HashMap contains no mapping 459 * for the key. 460 */ 461 final Entry<K,V> getEntry(Object key) { 462 if (size == 0) { 463 return null; 464 } 465 466 int hash = (key == null) ? 0 : hash(key); 467 for (Entry<K,V> e = table[indexFor(hash, table.length)]; 468 e != null; 469 e = e.next) { 470 Object k; 471 if (e.hash == hash && 472 ((k = e.key) == key || (key != null && key.equals(k)))) 473 return e; 474 } 475 return null; 476 } 477 478 /** 479 * Associates the specified value with the specified key in this map. 480 * If the map previously contained a mapping for the key, the old 481 * value is replaced. 482 * 483 * @param key key with which the specified value is to be associated 484 * @param value value to be associated with the specified key 485 * @return the previous value associated with <tt>key</tt>, or 486 * <tt>null</tt> if there was no mapping for <tt>key</tt>. 487 * (A <tt>null</tt> return can also indicate that the map 488 * previously associated <tt>null</tt> with <tt>key</tt>.) 489 */ 490 public V put(K key, V value) { 491 if (table == EMPTY_TABLE) { 492 inflateTable(threshold); 493 } 494 if (key == null) 495 return putForNullKey(value); 496 int hash = hash(key); 497 int i = indexFor(hash, table.length); 498 for (Entry<K,V> e = table[i]; e != null; e = e.next) { 499 Object k; 500 if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { 501 V oldValue = e.value; 502 e.value = value; 503 e.recordAccess(this); 504 return oldValue; 505 } 506 } 507 508 modCount++; 509 addEntry(hash, key, value, i); 510 return null; 511 } 512 513 /** 514 * Offloaded version of put for null keys 515 */ 516 private V putForNullKey(V value) { 517 for (Entry<K,V> e = table[0]; e != null; e = e.next) { 518 if (e.key == null) { 519 V oldValue = e.value; 520 e.value = value; 521 e.recordAccess(this); 522 return oldValue; 523 } 524 } 525 modCount++; 526 addEntry(0, null, value, 0); 527 return null; 528 } 529 530 /** 531 * This method is used instead of put by constructors and 532 * pseudoconstructors (clone, readObject). It does not resize the table, 533 * check for comodification, etc. It calls createEntry rather than 534 * addEntry. 535 */ 536 private void putForCreate(K key, V value) { 537 int hash = null == key ? 0 : hash(key); 538 int i = indexFor(hash, table.length); 539 540 /** 541 * Look for preexisting entry for key. This will never happen for 542 * clone or deserialize. It will only happen for construction if the 543 * input Map is a sorted map whose ordering is inconsistent w/ equals. 544 */ 545 for (Entry<K,V> e = table[i]; e != null; e = e.next) { 546 Object k; 547 if (e.hash == hash && 548 ((k = e.key) == key || (key != null && key.equals(k)))) { 549 e.value = value; 550 return; 551 } 552 } 553 554 createEntry(hash, key, value, i); 555 } 556 557 private void putAllForCreate(Map<? extends K, ? extends V> m) { 558 for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) 559 putForCreate(e.getKey(), e.getValue()); 560 } 561 562 /** 563 * Rehashes the contents of this map into a new array with a 564 * larger capacity. This method is called automatically when the 565 * number of keys in this map reaches its threshold. 566 * 567 * If current capacity is MAXIMUM_CAPACITY, this method does not 568 * resize the map, but sets threshold to Integer.MAX_VALUE. 569 * This has the effect of preventing future calls. 570 * 571 * @param newCapacity the new capacity, MUST be a power of two; 572 * must be greater than current capacity unless current 573 * capacity is MAXIMUM_CAPACITY (in which case value 574 * is irrelevant). 575 */ 576 void resize(int newCapacity) { 577 Entry[] oldTable = table; 578 int oldCapacity = oldTable.length; 579 if (oldCapacity == MAXIMUM_CAPACITY) { 580 threshold = Integer.MAX_VALUE; 581 return; 582 } 583 584 Entry[] newTable = new Entry[newCapacity]; 585 transfer(newTable, initHashSeedAsNeeded(newCapacity)); 586 table = newTable; 587 threshold = (int)Math.min(newCapacity * loadFactor, MAXIMUM_CAPACITY + 1); 588 } 589 590 /** 591 * Transfers all entries from current table to newTable. 592 */ 593 void transfer(Entry[] newTable, boolean rehash) { 594 int newCapacity = newTable.length; 595 for (Entry<K,V> e : table) { 596 while(null != e) { 597 Entry<K,V> next = e.next; 598 if (rehash) { 599 e.hash = null == e.key ? 0 : hash(e.key); 600 } 601 int i = indexFor(e.hash, newCapacity); 602 e.next = newTable[i]; 603 newTable[i] = e; 604 e = next; 605 } 606 } 607 } 608 609 /** 610 * Copies all of the mappings from the specified map to this map. 611 * These mappings will replace any mappings that this map had for 612 * any of the keys currently in the specified map. 613 * 614 * @param m mappings to be stored in this map 615 * @throws NullPointerException if the specified map is null 616 */ 617 public void putAll(Map<? extends K, ? extends V> m) { 618 int numKeysToBeAdded = m.size(); 619 if (numKeysToBeAdded == 0) 620 return; 621 622 if (table == EMPTY_TABLE) { 623 inflateTable((int) Math.max(numKeysToBeAdded * loadFactor, threshold)); 624 } 625 626 /* 627 * Expand the map if the map if the number of mappings to be added 628 * is greater than or equal to threshold. This is conservative; the 629 * obvious condition is (m.size() + size) >= threshold, but this 630 * condition could result in a map with twice the appropriate capacity, 631 * if the keys to be added overlap with the keys already in this map. 632 * By using the conservative calculation, we subject ourself 633 * to at most one extra resize. 634 */ 635 if (numKeysToBeAdded > threshold) { 636 int targetCapacity = (int)(numKeysToBeAdded / loadFactor + 1); 637 if (targetCapacity > MAXIMUM_CAPACITY) 638 targetCapacity = MAXIMUM_CAPACITY; 639 int newCapacity = table.length; 640 while (newCapacity < targetCapacity) 641 newCapacity <<= 1; 642 if (newCapacity > table.length) 643 resize(newCapacity); 644 } 645 646 for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) 647 put(e.getKey(), e.getValue()); 648 } 649 650 /** 651 * Removes the mapping for the specified key from this map if present. 652 * 653 * @param key key whose mapping is to be removed from the map 654 * @return the previous value associated with <tt>key</tt>, or 655 * <tt>null</tt> if there was no mapping for <tt>key</tt>. 656 * (A <tt>null</tt> return can also indicate that the map 657 * previously associated <tt>null</tt> with <tt>key</tt>.) 658 */ 659 public V remove(Object key) { 660 Entry<K,V> e = removeEntryForKey(key); 661 return (e == null ? null : e.value); 662 } 663 664 /** 665 * Removes and returns the entry associated with the specified key 666 * in the HashMap. Returns null if the HashMap contains no mapping 667 * for this key. 668 */ 669 final Entry<K,V> removeEntryForKey(Object key) { 670 if (size == 0) { 671 return null; 672 } 673 int hash = (key == null) ? 0 : hash(key); 674 int i = indexFor(hash, table.length); 675 Entry<K,V> prev = table[i]; 676 Entry<K,V> e = prev; 677 678 while (e != null) { 679 Entry<K,V> next = e.next; 680 Object k; 681 if (e.hash == hash && 682 ((k = e.key) == key || (key != null && key.equals(k)))) { 683 modCount++; 684 size--; 685 if (prev == e) 686 table[i] = next; 687 else 688 prev.next = next; 689 e.recordRemoval(this); 690 return e; 691 } 692 prev = e; 693 e = next; 694 } 695 696 return e; 697 } 698 699 /** 700 * Special version of remove for EntrySet using {@code Map.Entry.equals()} 701 * for matching. 702 */ 703 final Entry<K,V> removeMapping(Object o) { 704 if (size == 0 || !(o instanceof Map.Entry)) 705 return null; 706 707 Map.Entry<K,V> entry = (Map.Entry<K,V>) o; 708 Object key = entry.getKey(); 709 int hash = (key == null) ? 0 : hash(key); 710 int i = indexFor(hash, table.length); 711 Entry<K,V> prev = table[i]; 712 Entry<K,V> e = prev; 713 714 while (e != null) { 715 Entry<K,V> next = e.next; 716 if (e.hash == hash && e.equals(entry)) { 717 modCount++; 718 size--; 719 if (prev == e) 720 table[i] = next; 721 else 722 prev.next = next; 723 e.recordRemoval(this); 724 return e; 725 } 726 prev = e; 727 e = next; 728 } 729 730 return e; 731 } 732 733 /** 734 * Removes all of the mappings from this map. 735 * The map will be empty after this call returns. 736 */ 737 public void clear() { 738 modCount++; 739 Arrays.fill(table, null); 740 size = 0; 741 } 742 743 /** 744 * Returns <tt>true</tt> if this map maps one or more keys to the 745 * specified value. 746 * 747 * @param value value whose presence in this map is to be tested 748 * @return <tt>true</tt> if this map maps one or more keys to the 749 * specified value 750 */ 751 public boolean containsValue(Object value) { 752 if (value == null) 753 return containsNullValue(); 754 755 Entry[] tab = table; 756 for (int i = 0; i < tab.length ; i++) 757 for (Entry e = tab[i] ; e != null ; e = e.next) 758 if (value.equals(e.value)) 759 return true; 760 return false; 761 } 762 763 /** 764 * Special-case code for containsValue with null argument 765 */ 766 private boolean containsNullValue() { 767 Entry[] tab = table; 768 for (int i = 0; i < tab.length ; i++) 769 for (Entry e = tab[i] ; e != null ; e = e.next) 770 if (e.value == null) 771 return true; 772 return false; 773 } 774 775 /** 776 * Returns a shallow copy of this <tt>HashMap</tt> instance: the keys and 777 * values themselves are not cloned. 778 * 779 * @return a shallow copy of this map 780 */ 781 public Object clone() { 782 HashMap<K,V> result = null; 783 try { 784 result = (HashMap<K,V>)super.clone(); 785 } catch (CloneNotSupportedException e) { 786 // assert false; 787 } 788 if (result.table != EMPTY_TABLE) { 789 result.inflateTable(Math.min( 790 (int) Math.min( 791 size * Math.min(1 / loadFactor, 4.0f), 792 // we have limits... 793 HashMap.MAXIMUM_CAPACITY), 794 table.length)); 795 } 796 result.entrySet = null; 797 result.modCount = 0; 798 result.size = 0; 799 result.init(); 800 result.putAllForCreate(this); 801 802 return result; 803 } 804 805 static class Entry<K,V> implements Map.Entry<K,V> { 806 final K key; 807 V value; 808 Entry<K,V> next; 809 int hash; 810 811 /** 812 * Creates new entry. 813 */ 814 Entry(int h, K k, V v, Entry<K,V> n) { 815 value = v; 816 next = n; 817 key = k; 818 hash = h; 819 } 820 821 public final K getKey() { 822 return key; 823 } 824 825 public final V getValue() { 826 return value; 827 } 828 829 public final V setValue(V newValue) { 830 V oldValue = value; 831 value = newValue; 832 return oldValue; 833 } 834 835 public final boolean equals(Object o) { 836 if (!(o instanceof Map.Entry)) 837 return false; 838 Map.Entry e = (Map.Entry)o; 839 Object k1 = getKey(); 840 Object k2 = e.getKey(); 841 if (k1 == k2 || (k1 != null && k1.equals(k2))) { 842 Object v1 = getValue(); 843 Object v2 = e.getValue(); 844 if (v1 == v2 || (v1 != null && v1.equals(v2))) 845 return true; 846 } 847 return false; 848 } 849 850 public final int hashCode() { 851 return Objects.hashCode(getKey()) ^ Objects.hashCode(getValue()); 852 } 853 854 public final String toString() { 855 return getKey() + "=" + getValue(); 856 } 857 858 /** 859 * This method is invoked whenever the value in an entry is 860 * overwritten by an invocation of put(k,v) for a key k that's already 861 * in the HashMap. 862 */ 863 void recordAccess(HashMap<K,V> m) { 864 } 865 866 /** 867 * This method is invoked whenever the entry is 868 * removed from the table. 869 */ 870 void recordRemoval(HashMap<K,V> m) { 871 } 872 } 873 874 /** 875 * Adds a new entry with the specified key, value and hash code to 876 * the specified bucket. It is the responsibility of this 877 * method to resize the table if appropriate. 878 * 879 * Subclass overrides this to alter the behavior of put method. 880 */ 881 void addEntry(int hash, K key, V value, int bucketIndex) { 882 if ((size >= threshold) && (null != table[bucketIndex])) { 883 resize(2 * table.length); 884 hash = (null != key) ? hash(key) : 0; 885 bucketIndex = indexFor(hash, table.length); 886 } 887 888 createEntry(hash, key, value, bucketIndex); 889 } 890 891 /** 892 * Like addEntry except that this version is used when creating entries 893 * as part of Map construction or "pseudo-construction" (cloning, 894 * deserialization). This version needn't worry about resizing the table. 895 * 896 * Subclass overrides this to alter the behavior of HashMap(Map), 897 * clone, and readObject. 898 */ 899 void createEntry(int hash, K key, V value, int bucketIndex) { 900 Entry<K,V> e = table[bucketIndex]; 901 table[bucketIndex] = new Entry<>(hash, key, value, e); 902 size++; 903 } 904 905 private abstract class HashIterator<E> implements Iterator<E> { 906 Entry<K,V> next; // next entry to return 907 int expectedModCount; // For fast-fail 908 int index; // current slot 909 Entry<K,V> current; // current entry 910 911 HashIterator() { 912 expectedModCount = modCount; 913 if (size > 0) { // advance to first entry 914 Entry[] t = table; 915 while (index < t.length && (next = t[index++]) == null) 916 ; 917 } 918 } 919 920 public final boolean hasNext() { 921 return next != null; 922 } 923 924 final Entry<K,V> nextEntry() { 925 if (modCount != expectedModCount) 926 throw new ConcurrentModificationException(); 927 Entry<K,V> e = next; 928 if (e == null) 929 throw new NoSuchElementException(); 930 931 if ((next = e.next) == null) { 932 Entry[] t = table; 933 while (index < t.length && (next = t[index++]) == null) 934 ; 935 } 936 current = e; 937 return e; 938 } 939 940 public void remove() { 941 if (current == null) 942 throw new IllegalStateException(); 943 if (modCount != expectedModCount) 944 throw new ConcurrentModificationException(); 945 Object k = current.key; 946 current = null; 947 HashMap.this.removeEntryForKey(k); 948 expectedModCount = modCount; 949 } 950 } 951 952 private final class ValueIterator extends HashIterator<V> { 953 public V next() { 954 return nextEntry().value; 955 } 956 } 957 958 private final class KeyIterator extends HashIterator<K> { 959 public K next() { 960 return nextEntry().getKey(); 961 } 962 } 963 964 private final class EntryIterator extends HashIterator<Map.Entry<K,V>> { 965 public Map.Entry<K,V> next() { 966 return nextEntry(); 967 } 968 } 969 970 // Subclass overrides these to alter behavior of views' iterator() method 971 Iterator<K> newKeyIterator() { 972 return new KeyIterator(); 973 } 974 Iterator<V> newValueIterator() { 975 return new ValueIterator(); 976 } 977 Iterator<Map.Entry<K,V>> newEntryIterator() { 978 return new EntryIterator(); 979 } 980 981 982 // Views 983 984 private transient Set<Map.Entry<K,V>> entrySet = null; 985 986 /** 987 * Returns a {@link Set} view of the keys contained in this map. 988 * The set is backed by the map, so changes to the map are 989 * reflected in the set, and vice-versa. If the map is modified 990 * while an iteration over the set is in progress (except through 991 * the iterator's own <tt>remove</tt> operation), the results of 992 * the iteration are undefined. The set supports element removal, 993 * which removes the corresponding mapping from the map, via the 994 * <tt>Iterator.remove</tt>, <tt>Set.remove</tt>, 995 * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt> 996 * operations. It does not support the <tt>add</tt> or <tt>addAll</tt> 997 * operations. 998 */ 999 public Set<K> keySet() { 1000 Set<K> ks = keySet; 1001 return (ks != null ? ks : (keySet = new KeySet())); 1002 } 1003 1004 private final class KeySet extends AbstractSet<K> { 1005 public Iterator<K> iterator() { 1006 return newKeyIterator(); 1007 } 1008 public int size() { 1009 return size; 1010 } 1011 public boolean contains(Object o) { 1012 return containsKey(o); 1013 } 1014 public boolean remove(Object o) { 1015 return HashMap.this.removeEntryForKey(o) != null; 1016 } 1017 public void clear() { 1018 HashMap.this.clear(); 1019 } 1020 } 1021 1022 /** 1023 * Returns a {@link Collection} view of the values contained in this map. 1024 * The collection is backed by the map, so changes to the map are 1025 * reflected in the collection, and vice-versa. If the map is 1026 * modified while an iteration over the collection is in progress 1027 * (except through the iterator's own <tt>remove</tt> operation), 1028 * the results of the iteration are undefined. The collection 1029 * supports element removal, which removes the corresponding 1030 * mapping from the map, via the <tt>Iterator.remove</tt>, 1031 * <tt>Collection.remove</tt>, <tt>removeAll</tt>, 1032 * <tt>retainAll</tt> and <tt>clear</tt> operations. It does not 1033 * support the <tt>add</tt> or <tt>addAll</tt> operations. 1034 */ 1035 public Collection<V> values() { 1036 Collection<V> vs = values; 1037 return (vs != null ? vs : (values = new Values())); 1038 } 1039 1040 private final class Values extends AbstractCollection<V> { 1041 public Iterator<V> iterator() { 1042 return newValueIterator(); 1043 } 1044 public int size() { 1045 return size; 1046 } 1047 public boolean contains(Object o) { 1048 return containsValue(o); 1049 } 1050 public void clear() { 1051 HashMap.this.clear(); 1052 } 1053 } 1054 1055 /** 1056 * Returns a {@link Set} view of the mappings contained in this map. 1057 * The set is backed by the map, so changes to the map are 1058 * reflected in the set, and vice-versa. If the map is modified 1059 * while an iteration over the set is in progress (except through 1060 * the iterator's own <tt>remove</tt> operation, or through the 1061 * <tt>setValue</tt> operation on a map entry returned by the 1062 * iterator) the results of the iteration are undefined. The set 1063 * supports element removal, which removes the corresponding 1064 * mapping from the map, via the <tt>Iterator.remove</tt>, 1065 * <tt>Set.remove</tt>, <tt>removeAll</tt>, <tt>retainAll</tt> and 1066 * <tt>clear</tt> operations. It does not support the 1067 * <tt>add</tt> or <tt>addAll</tt> operations. 1068 * 1069 * @return a set view of the mappings contained in this map 1070 */ 1071 public Set<Map.Entry<K,V>> entrySet() { 1072 return entrySet0(); 1073 } 1074 1075 private Set<Map.Entry<K,V>> entrySet0() { 1076 Set<Map.Entry<K,V>> es = entrySet; 1077 return es != null ? es : (entrySet = new EntrySet()); 1078 } 1079 1080 private final class EntrySet extends AbstractSet<Map.Entry<K,V>> { 1081 public Iterator<Map.Entry<K,V>> iterator() { 1082 return newEntryIterator(); 1083 } 1084 public boolean contains(Object o) { 1085 if (!(o instanceof Map.Entry)) 1086 return false; 1087 Map.Entry<K,V> e = (Map.Entry<K,V>) o; 1088 Entry<K,V> candidate = getEntry(e.getKey()); 1089 return candidate != null && candidate.equals(e); 1090 } 1091 public boolean remove(Object o) { 1092 return removeMapping(o) != null; 1093 } 1094 public int size() { 1095 return size; 1096 } 1097 public void clear() { 1098 HashMap.this.clear(); 1099 } 1100 } 1101 1102 /** 1103 * Save the state of the <tt>HashMap</tt> instance to a stream (i.e., 1104 * serialize it). 1105 * 1106 * @serialData The <i>capacity</i> of the HashMap (the length of the 1107 * bucket array) is emitted (int), followed by the 1108 * <i>size</i> (an int, the number of key-value 1109 * mappings), followed by the key (Object) and value (Object) 1110 * for each key-value mapping. The key-value mappings are 1111 * emitted in no particular order. 1112 */ 1113 private void writeObject(java.io.ObjectOutputStream s) 1114 throws IOException 1115 { 1116 // Write out the threshold, loadfactor, and any hidden stuff 1117 s.defaultWriteObject(); 1118 1119 // Write out number of buckets 1120 if (table==EMPTY_TABLE) { 1121 s.writeInt(roundUpToPowerOf2(threshold)); 1122 } else { 1123 s.writeInt(table.length); 1124 } 1125 1126 // Write out size (number of Mappings) 1127 s.writeInt(size); 1128 1129 // Write out keys and values (alternating) 1130 if (size > 0) { 1131 for(Map.Entry<K,V> e : entrySet0()) { 1132 s.writeObject(e.getKey()); 1133 s.writeObject(e.getValue()); 1134 } 1135 } 1136 } 1137 1138 private static final long serialVersionUID = 362498820763181265L; 1139 1140 /** 1141 * Reconstitute the {@code HashMap} instance from a stream (i.e., 1142 * deserialize it). 1143 */ 1144 private void readObject(java.io.ObjectInputStream s) 1145 throws IOException, ClassNotFoundException 1146 { 1147 // Read in the threshold (ignored), loadfactor, and any hidden stuff 1148 s.defaultReadObject(); 1149 if (loadFactor <= 0 || Float.isNaN(loadFactor)) { 1150 throw new InvalidObjectException("Illegal load factor: " + 1151 loadFactor); 1152 } 1153 1154 // set other fields that need values 1155 table = (Entry<K,V>[]) EMPTY_TABLE; 1156 1157 // Read in number of buckets 1158 s.readInt(); // ignored. 1159 1160 // Read number of mappings 1161 int mappings = s.readInt(); 1162 if (mappings < 0) 1163 throw new InvalidObjectException("Illegal mappings count: " + 1164 mappings); 1165 1166 // capacity chosen by number of mappings and desired load (if >= 0.25) 1167 int capacity = (int) Math.min( 1168 mappings * Math.min(1 / loadFactor, 4.0f), 1169 // we have limits... 1170 HashMap.MAXIMUM_CAPACITY); 1171 1172 // allocate the bucket array; 1173 if (mappings > 0) { 1174 inflateTable(capacity); 1175 } else { 1176 threshold = capacity; 1177 } 1178 1179 init(); // Give subclass a chance to do its thing. 1180 1181 // Read the keys and values, and put the mappings in the HashMap 1182 for (int i = 0; i < mappings; i++) { 1183 K key = (K) s.readObject(); 1184 V value = (V) s.readObject(); 1185 putForCreate(key, value); 1186 } 1187 } 1188 1189 // These methods are used when serializing HashSets 1190 int capacity() { return table.length; } 1191 float loadFactor() { return loadFactor; } 1192 }