1/* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18package java.util; 19 20import java.io.IOException; 21import java.io.InvalidObjectException; 22import java.io.ObjectInputStream; 23import java.io.ObjectOutputStream; 24import java.io.ObjectStreamField; 25import java.io.Serializable; 26import libcore.util.Objects; 27 28/** 29 * HashMap is an implementation of {@link Map}. All optional operations are supported. 30 * 31 * <p>All elements are permitted as keys or values, including null. 32 * 33 * <p>Note that the iteration order for HashMap is non-deterministic. If you want 34 * deterministic iteration, use {@link LinkedHashMap}. 35 * 36 * <p>Note: the implementation of {@code HashMap} is not synchronized. 37 * If one thread of several threads accessing an instance modifies the map 38 * structurally, access to the map needs to be synchronized. A structural 39 * modification is an operation that adds or removes an entry. Changes in 40 * the value of an entry are not structural changes. 41 * 42 * <p>The {@code Iterator} created by calling the {@code iterator} method 43 * may throw a {@code ConcurrentModificationException} if the map is structurally 44 * changed while an iterator is used to iterate over the elements. Only the 45 * {@code remove} method that is provided by the iterator allows for removal of 46 * elements during iteration. It is not possible to guarantee that this 47 * mechanism works in all cases of unsynchronized concurrent modification. It 48 * should only be used for debugging purposes. 49 * 50 * @param <K> the type of keys maintained by this map 51 * @param <V> the type of mapped values 52 */ 53public class HashMap<K, V> extends AbstractMap<K, V> implements Cloneable, Serializable { 54 /** 55 * Min capacity (other than zero) for a HashMap. Must be a power of two 56 * greater than 1 (and less than 1 << 30). 57 */ 58 private static final int MINIMUM_CAPACITY = 4; 59 60 /** 61 * Max capacity for a HashMap. Must be a power of two >= MINIMUM_CAPACITY. 62 */ 63 private static final int MAXIMUM_CAPACITY = 1 << 30; 64 65 /** 66 * An empty table shared by all zero-capacity maps (typically from default 67 * constructor). It is never written to, and replaced on first put. Its size 68 * is set to half the minimum, so that the first resize will create a 69 * minimum-sized table. 70 */ 71 private static final Entry[] EMPTY_TABLE 72 = new HashMapEntry[MINIMUM_CAPACITY >>> 1]; 73 74 /** 75 * The default load factor. Note that this implementation ignores the 76 * load factor, but cannot do away with it entirely because it's 77 * mentioned in the API. 78 * 79 * <p>Note that this constant has no impact on the behavior of the program, 80 * but it is emitted as part of the serialized form. The load factor of 81 * .75 is hardwired into the program, which uses cheap shifts in place of 82 * expensive division. 83 */ 84 static final float DEFAULT_LOAD_FACTOR = .75F; 85 86 /** 87 * The hash table. If this hash map contains a mapping for null, it is 88 * not represented this hash table. 89 */ 90 transient HashMapEntry<K, V>[] table; 91 92 /** 93 * The entry representing the null key, or null if there's no such mapping. 94 */ 95 transient HashMapEntry<K, V> entryForNullKey; 96 97 /** 98 * The number of mappings in this hash map. 99 */ 100 transient int size; 101 102 /** 103 * Incremented by "structural modifications" to allow (best effort) 104 * detection of concurrent modification. 105 */ 106 transient int modCount; 107 108 /** 109 * The table is rehashed when its size exceeds this threshold. 110 * The value of this field is generally .75 * capacity, except when 111 * the capacity is zero, as described in the EMPTY_TABLE declaration 112 * above. 113 */ 114 private transient int threshold; 115 116 // Views - lazily initialized 117 private transient Set<K> keySet; 118 private transient Set<Entry<K, V>> entrySet; 119 private transient Collection<V> values; 120 121 /** 122 * Constructs a new empty {@code HashMap} instance. 123 */ 124 @SuppressWarnings("unchecked") 125 public HashMap() { 126 table = (HashMapEntry<K, V>[]) EMPTY_TABLE; 127 threshold = -1; // Forces first put invocation to replace EMPTY_TABLE 128 } 129 130 /** 131 * Constructs a new {@code HashMap} instance with the specified capacity. 132 * 133 * @param capacity 134 * the initial capacity of this hash map. 135 * @throws IllegalArgumentException 136 * when the capacity is less than zero. 137 */ 138 public HashMap(int capacity) { 139 if (capacity < 0) { 140 throw new IllegalArgumentException("Capacity: " + capacity); 141 } 142 143 if (capacity == 0) { 144 @SuppressWarnings("unchecked") 145 HashMapEntry<K, V>[] tab = (HashMapEntry<K, V>[]) EMPTY_TABLE; 146 table = tab; 147 threshold = -1; // Forces first put() to replace EMPTY_TABLE 148 return; 149 } 150 151 if (capacity < MINIMUM_CAPACITY) { 152 capacity = MINIMUM_CAPACITY; 153 } else if (capacity > MAXIMUM_CAPACITY) { 154 capacity = MAXIMUM_CAPACITY; 155 } else { 156 capacity = roundUpToPowerOfTwo(capacity); 157 } 158 makeTable(capacity); 159 } 160 161 /** 162 * Constructs a new {@code HashMap} instance with the specified capacity and 163 * load factor. 164 * 165 * @param capacity 166 * the initial capacity of this hash map. 167 * @param loadFactor 168 * the initial load factor. 169 * @throws IllegalArgumentException 170 * when the capacity is less than zero or the load factor is 171 * less or equal to zero or NaN. 172 */ 173 public HashMap(int capacity, float loadFactor) { 174 this(capacity); 175 176 if (loadFactor <= 0 || Float.isNaN(loadFactor)) { 177 throw new IllegalArgumentException("Load factor: " + loadFactor); 178 } 179 180 /* 181 * Note that this implementation ignores loadFactor; it always uses 182 * a load factor of 3/4. This simplifies the code and generally 183 * improves performance. 184 */ 185 } 186 187 /** 188 * Constructs a new {@code HashMap} instance containing the mappings from 189 * the specified map. 190 * 191 * @param map 192 * the mappings to add. 193 */ 194 public HashMap(Map<? extends K, ? extends V> map) { 195 this(capacityForInitSize(map.size())); 196 constructorPutAll(map); 197 } 198 199 /** 200 * Inserts all of the elements of map into this HashMap in a manner 201 * suitable for use by constructors and pseudo-constructors (i.e., clone, 202 * readObject). Also used by LinkedHashMap. 203 */ 204 final void constructorPutAll(Map<? extends K, ? extends V> map) { 205 for (Entry<? extends K, ? extends V> e : map.entrySet()) { 206 constructorPut(e.getKey(), e.getValue()); 207 } 208 } 209 210 /** 211 * Returns an appropriate capacity for the specified initial size. Does 212 * not round the result up to a power of two; the caller must do this! 213 * The returned value will be between 0 and MAXIMUM_CAPACITY (inclusive). 214 */ 215 static int capacityForInitSize(int size) { 216 int result = (size >> 1) + size; // Multiply by 3/2 to allow for growth 217 218 // boolean expr is equivalent to result >= 0 && result<MAXIMUM_CAPACITY 219 return (result & ~(MAXIMUM_CAPACITY-1))==0 ? result : MAXIMUM_CAPACITY; 220 } 221 222 /** 223 * Returns a shallow copy of this map. 224 * 225 * @return a shallow copy of this map. 226 */ 227 @SuppressWarnings("unchecked") 228 @Override public Object clone() { 229 /* 230 * This could be made more efficient. It unnecessarily hashes all of 231 * the elements in the map. 232 */ 233 HashMap<K, V> result; 234 try { 235 result = (HashMap<K, V>) super.clone(); 236 } catch (CloneNotSupportedException e) { 237 throw new AssertionError(e); 238 } 239 240 // Restore clone to empty state, retaining our capacity and threshold 241 result.makeTable(table.length); 242 result.entryForNullKey = null; 243 result.size = 0; 244 result.keySet = null; 245 result.entrySet = null; 246 result.values = null; 247 248 result.init(); // Give subclass a chance to initialize itself 249 result.constructorPutAll(this); // Calls method overridden in subclass!! 250 return result; 251 } 252 253 /** 254 * This method is called from the pseudo-constructors (clone and readObject) 255 * prior to invoking constructorPut/constructorPutAll, which invoke the 256 * overridden constructorNewEntry method. Normally it is a VERY bad idea to 257 * invoke an overridden method from a pseudo-constructor (Effective Java 258 * Item 17). In this case it is unavoidable, and the init method provides a 259 * workaround. 260 */ 261 void init() { } 262 263 /** 264 * Returns whether this map is empty. 265 * 266 * @return {@code true} if this map has no elements, {@code false} 267 * otherwise. 268 * @see #size() 269 */ 270 @Override public boolean isEmpty() { 271 return size == 0; 272 } 273 274 /** 275 * Returns the number of elements in this map. 276 * 277 * @return the number of elements in this map. 278 */ 279 @Override public int size() { 280 return size; 281 } 282 283 /** 284 * Returns the value of the mapping with the specified key. 285 * 286 * @param key 287 * the key. 288 * @return the value of the mapping with the specified key, or {@code null} 289 * if no mapping for the specified key is found. 290 */ 291 public V get(Object key) { 292 if (key == null) { 293 HashMapEntry<K, V> e = entryForNullKey; 294 return e == null ? null : e.value; 295 } 296 297 // Doug Lea's supplemental secondaryHash function (inlined) 298 int hash = key.hashCode(); 299 hash ^= (hash >>> 20) ^ (hash >>> 12); 300 hash ^= (hash >>> 7) ^ (hash >>> 4); 301 302 HashMapEntry<K, V>[] tab = table; 303 for (HashMapEntry<K, V> e = tab[hash & (tab.length - 1)]; 304 e != null; e = e.next) { 305 K eKey = e.key; 306 if (eKey == key || (e.hash == hash && key.equals(eKey))) { 307 return e.value; 308 } 309 } 310 return null; 311 } 312 313 /** 314 * Returns whether this map contains the specified key. 315 * 316 * @param key 317 * the key to search for. 318 * @return {@code true} if this map contains the specified key, 319 * {@code false} otherwise. 320 */ 321 @Override public boolean containsKey(Object key) { 322 if (key == null) { 323 return entryForNullKey != null; 324 } 325 326 // Doug Lea's supplemental secondaryHash function (inlined) 327 int hash = key.hashCode(); 328 hash ^= (hash >>> 20) ^ (hash >>> 12); 329 hash ^= (hash >>> 7) ^ (hash >>> 4); 330 331 HashMapEntry<K, V>[] tab = table; 332 for (HashMapEntry<K, V> e = tab[hash & (tab.length - 1)]; 333 e != null; e = e.next) { 334 K eKey = e.key; 335 if (eKey == key || (e.hash == hash && key.equals(eKey))) { 336 return true; 337 } 338 } 339 return false; 340 } 341 342 /** 343 * Returns whether this map contains the specified value. 344 * 345 * @param value 346 * the value to search for. 347 * @return {@code true} if this map contains the specified value, 348 * {@code false} otherwise. 349 */ 350 @Override public boolean containsValue(Object value) { 351 HashMapEntry[] tab = table; 352 int len = tab.length; 353 if (value == null) { 354 for (int i = 0; i < len; i++) { 355 for (HashMapEntry e = tab[i]; e != null; e = e.next) { 356 if (e.value == null) { 357 return true; 358 } 359 } 360 } 361 return entryForNullKey != null && entryForNullKey.value == null; 362 } 363 364 // value is non-null 365 for (int i = 0; i < len; i++) { 366 for (HashMapEntry e = tab[i]; e != null; e = e.next) { 367 if (value.equals(e.value)) { 368 return true; 369 } 370 } 371 } 372 return entryForNullKey != null && value.equals(entryForNullKey.value); 373 } 374 375 /** 376 * Maps the specified key to the specified value. 377 * 378 * @param key 379 * the key. 380 * @param value 381 * the value. 382 * @return the value of any previous mapping with the specified key or 383 * {@code null} if there was no such mapping. 384 */ 385 @Override public V put(K key, V value) { 386 if (key == null) { 387 return putValueForNullKey(value); 388 } 389 390 int hash = secondaryHash(key.hashCode()); 391 HashMapEntry<K, V>[] tab = table; 392 int index = hash & (tab.length - 1); 393 for (HashMapEntry<K, V> e = tab[index]; e != null; e = e.next) { 394 if (e.hash == hash && key.equals(e.key)) { 395 preModify(e); 396 V oldValue = e.value; 397 e.value = value; 398 return oldValue; 399 } 400 } 401 402 // No entry for (non-null) key is present; create one 403 modCount++; 404 if (size++ > threshold) { 405 tab = doubleCapacity(); 406 index = hash & (tab.length - 1); 407 } 408 addNewEntry(key, value, hash, index); 409 return null; 410 } 411 412 private V putValueForNullKey(V value) { 413 HashMapEntry<K, V> entry = entryForNullKey; 414 if (entry == null) { 415 addNewEntryForNullKey(value); 416 size++; 417 modCount++; 418 return null; 419 } else { 420 preModify(entry); 421 V oldValue = entry.value; 422 entry.value = value; 423 return oldValue; 424 } 425 } 426 427 /** 428 * Give LinkedHashMap a chance to take action when we modify an existing 429 * entry. 430 * 431 * @param e the entry we're about to modify. 432 */ 433 void preModify(HashMapEntry<K, V> e) { } 434 435 /** 436 * This method is just like put, except that it doesn't do things that 437 * are inappropriate or unnecessary for constructors and pseudo-constructors 438 * (i.e., clone, readObject). In particular, this method does not check to 439 * ensure that capacity is sufficient, and does not increment modCount. 440 */ 441 private void constructorPut(K key, V value) { 442 if (key == null) { 443 HashMapEntry<K, V> entry = entryForNullKey; 444 if (entry == null) { 445 entryForNullKey = constructorNewEntry(null, value, 0, null); 446 size++; 447 } else { 448 entry.value = value; 449 } 450 return; 451 } 452 453 int hash = secondaryHash(key.hashCode()); 454 HashMapEntry<K, V>[] tab = table; 455 int index = hash & (tab.length - 1); 456 HashMapEntry<K, V> first = tab[index]; 457 for (HashMapEntry<K, V> e = first; e != null; e = e.next) { 458 if (e.hash == hash && key.equals(e.key)) { 459 e.value = value; 460 return; 461 } 462 } 463 464 // No entry for (non-null) key is present; create one 465 tab[index] = constructorNewEntry(key, value, hash, first); 466 size++; 467 } 468 469 /** 470 * Creates a new entry for the given key, value, hash, and index and 471 * inserts it into the hash table. This method is called by put 472 * (and indirectly, putAll), and overridden by LinkedHashMap. The hash 473 * must incorporate the secondary hash function. 474 */ 475 void addNewEntry(K key, V value, int hash, int index) { 476 table[index] = new HashMapEntry<K, V>(key, value, hash, table[index]); 477 } 478 479 /** 480 * Creates a new entry for the null key, and the given value and 481 * inserts it into the hash table. This method is called by put 482 * (and indirectly, putAll), and overridden by LinkedHashMap. 483 */ 484 void addNewEntryForNullKey(V value) { 485 entryForNullKey = new HashMapEntry<K, V>(null, value, 0, null); 486 } 487 488 /** 489 * Like newEntry, but does not perform any activity that would be 490 * unnecessary or inappropriate for constructors. In this class, the 491 * two methods behave identically; in LinkedHashMap, they differ. 492 */ 493 HashMapEntry<K, V> constructorNewEntry( 494 K key, V value, int hash, HashMapEntry<K, V> first) { 495 return new HashMapEntry<K, V>(key, value, hash, first); 496 } 497 498 /** 499 * Copies all the mappings in the specified map to this map. These mappings 500 * will replace all mappings that this map had for any of the keys currently 501 * in the given map. 502 * 503 * @param map 504 * the map to copy mappings from. 505 */ 506 @Override public void putAll(Map<? extends K, ? extends V> map) { 507 ensureCapacity(map.size()); 508 super.putAll(map); 509 } 510 511 /** 512 * Ensures that the hash table has sufficient capacity to store the 513 * specified number of mappings, with room to grow. If not, it increases the 514 * capacity as appropriate. Like doubleCapacity, this method moves existing 515 * entries to new buckets as appropriate. Unlike doubleCapacity, this method 516 * can grow the table by factors of 2^n for n > 1. Hopefully, a single call 517 * to this method will be faster than multiple calls to doubleCapacity. 518 * 519 * <p>This method is called only by putAll. 520 */ 521 private void ensureCapacity(int numMappings) { 522 int newCapacity = roundUpToPowerOfTwo(capacityForInitSize(numMappings)); 523 HashMapEntry<K, V>[] oldTable = table; 524 int oldCapacity = oldTable.length; 525 if (newCapacity <= oldCapacity) { 526 return; 527 } 528 if (newCapacity == oldCapacity * 2) { 529 doubleCapacity(); 530 return; 531 } 532 533 // We're growing by at least 4x, rehash in the obvious way 534 HashMapEntry<K, V>[] newTable = makeTable(newCapacity); 535 if (size != 0) { 536 int newMask = newCapacity - 1; 537 for (int i = 0; i < oldCapacity; i++) { 538 for (HashMapEntry<K, V> e = oldTable[i]; e != null;) { 539 HashMapEntry<K, V> oldNext = e.next; 540 int newIndex = e.hash & newMask; 541 HashMapEntry<K, V> newNext = newTable[newIndex]; 542 newTable[newIndex] = e; 543 e.next = newNext; 544 e = oldNext; 545 } 546 } 547 } 548 } 549 550 /** 551 * Allocate a table of the given capacity and set the threshold accordingly. 552 * @param newCapacity must be a power of two 553 */ 554 private HashMapEntry<K, V>[] makeTable(int newCapacity) { 555 @SuppressWarnings("unchecked") HashMapEntry<K, V>[] newTable 556 = (HashMapEntry<K, V>[]) new HashMapEntry[newCapacity]; 557 table = newTable; 558 threshold = (newCapacity >> 1) + (newCapacity >> 2); // 3/4 capacity 559 return newTable; 560 } 561 562 /** 563 * Doubles the capacity of the hash table. Existing entries are placed in 564 * the correct bucket on the enlarged table. If the current capacity is, 565 * MAXIMUM_CAPACITY, this method is a no-op. Returns the table, which 566 * will be new unless we were already at MAXIMUM_CAPACITY. 567 */ 568 private HashMapEntry<K, V>[] doubleCapacity() { 569 HashMapEntry<K, V>[] oldTable = table; 570 int oldCapacity = oldTable.length; 571 if (oldCapacity == MAXIMUM_CAPACITY) { 572 return oldTable; 573 } 574 int newCapacity = oldCapacity * 2; 575 HashMapEntry<K, V>[] newTable = makeTable(newCapacity); 576 if (size == 0) { 577 return newTable; 578 } 579 580 for (int j = 0; j < oldCapacity; j++) { 581 /* 582 * Rehash the bucket using the minimum number of field writes. 583 * This is the most subtle and delicate code in the class. 584 */ 585 HashMapEntry<K, V> e = oldTable[j]; 586 if (e == null) { 587 continue; 588 } 589 int highBit = e.hash & oldCapacity; 590 HashMapEntry<K, V> broken = null; 591 newTable[j | highBit] = e; 592 for (HashMapEntry<K, V> n = e.next; n != null; e = n, n = n.next) { 593 int nextHighBit = n.hash & oldCapacity; 594 if (nextHighBit != highBit) { 595 if (broken == null) 596 newTable[j | nextHighBit] = n; 597 else 598 broken.next = n; 599 broken = e; 600 highBit = nextHighBit; 601 } 602 } 603 if (broken != null) 604 broken.next = null; 605 } 606 return newTable; 607 } 608 609 /** 610 * Removes the mapping with the specified key from this map. 611 * 612 * @param key 613 * the key of the mapping to remove. 614 * @return the value of the removed mapping or {@code null} if no mapping 615 * for the specified key was found. 616 */ 617 @Override public V remove(Object key) { 618 if (key == null) { 619 return removeNullKey(); 620 } 621 int hash = secondaryHash(key.hashCode()); 622 HashMapEntry<K, V>[] tab = table; 623 int index = hash & (tab.length - 1); 624 for (HashMapEntry<K, V> e = tab[index], prev = null; 625 e != null; prev = e, e = e.next) { 626 if (e.hash == hash && key.equals(e.key)) { 627 if (prev == null) { 628 tab[index] = e.next; 629 } else { 630 prev.next = e.next; 631 } 632 modCount++; 633 size--; 634 postRemove(e); 635 return e.value; 636 } 637 } 638 return null; 639 } 640 641 private V removeNullKey() { 642 HashMapEntry<K, V> e = entryForNullKey; 643 if (e == null) { 644 return null; 645 } 646 entryForNullKey = null; 647 modCount++; 648 size--; 649 postRemove(e); 650 return e.value; 651 } 652 653 /** 654 * Subclass overrides this method to unlink entry. 655 */ 656 void postRemove(HashMapEntry<K, V> e) { } 657 658 /** 659 * Removes all mappings from this hash map, leaving it empty. 660 * 661 * @see #isEmpty 662 * @see #size 663 */ 664 @Override public void clear() { 665 if (size != 0) { 666 Arrays.fill(table, null); 667 entryForNullKey = null; 668 modCount++; 669 size = 0; 670 } 671 } 672 673 /** 674 * Returns a set of the keys contained in this map. The set is backed by 675 * this map so changes to one are reflected by the other. The set does not 676 * support adding. 677 * 678 * @return a set of the keys. 679 */ 680 @Override public Set<K> keySet() { 681 Set<K> ks = keySet; 682 return (ks != null) ? ks : (keySet = new KeySet()); 683 } 684 685 /** 686 * Returns a collection of the values contained in this map. The collection 687 * is backed by this map so changes to one are reflected by the other. The 688 * collection supports remove, removeAll, retainAll and clear operations, 689 * and it does not support add or addAll operations. 690 * <p> 691 * This method returns a collection which is the subclass of 692 * AbstractCollection. The iterator method of this subclass returns a 693 * "wrapper object" over the iterator of map's entrySet(). The {@code size} 694 * method wraps the map's size method and the {@code contains} method wraps 695 * the map's containsValue method. 696 * </p> 697 * <p> 698 * The collection is created when this method is called for the first time 699 * and returned in response to all subsequent calls. This method may return 700 * different collections when multiple concurrent calls occur, since no 701 * synchronization is performed. 702 * </p> 703 * 704 * @return a collection of the values contained in this map. 705 */ 706 @Override public Collection<V> values() { 707 Collection<V> vs = values; 708 return (vs != null) ? vs : (values = new Values()); 709 } 710 711 /** 712 * Returns a set containing all of the mappings in this map. Each mapping is 713 * an instance of {@link Map.Entry}. As the set is backed by this map, 714 * changes in one will be reflected in the other. 715 * 716 * @return a set of the mappings. 717 */ 718 public Set<Entry<K, V>> entrySet() { 719 Set<Entry<K, V>> es = entrySet; 720 return (es != null) ? es : (entrySet = new EntrySet()); 721 } 722 723 static class HashMapEntry<K, V> implements Entry<K, V> { 724 final K key; 725 V value; 726 final int hash; 727 HashMapEntry<K, V> next; 728 729 HashMapEntry(K key, V value, int hash, HashMapEntry<K, V> next) { 730 this.key = key; 731 this.value = value; 732 this.hash = hash; 733 this.next = next; 734 } 735 736 public final K getKey() { 737 return key; 738 } 739 740 public final V getValue() { 741 return value; 742 } 743 744 public final V setValue(V value) { 745 V oldValue = this.value; 746 this.value = value; 747 return oldValue; 748 } 749 750 @Override public final boolean equals(Object o) { 751 if (!(o instanceof Entry)) { 752 return false; 753 } 754 Entry<?, ?> e = (Entry<?, ?>) o; 755 return Objects.equal(e.getKey(), key) 756 && Objects.equal(e.getValue(), value); 757 } 758 759 @Override public final int hashCode() { 760 return (key == null ? 0 : key.hashCode()) ^ 761 (value == null ? 0 : value.hashCode()); 762 } 763 764 @Override public final String toString() { 765 return key + "=" + value; 766 } 767 } 768 769 private abstract class HashIterator { 770 int nextIndex; 771 HashMapEntry<K, V> nextEntry = entryForNullKey; 772 HashMapEntry<K, V> lastEntryReturned; 773 int expectedModCount = modCount; 774 775 HashIterator() { 776 if (nextEntry == null) { 777 HashMapEntry<K, V>[] tab = table; 778 HashMapEntry<K, V> next = null; 779 while (next == null && nextIndex < tab.length) { 780 next = tab[nextIndex++]; 781 } 782 nextEntry = next; 783 } 784 } 785 786 public boolean hasNext() { 787 return nextEntry != null; 788 } 789 790 HashMapEntry<K, V> nextEntry() { 791 if (modCount != expectedModCount) 792 throw new ConcurrentModificationException(); 793 if (nextEntry == null) 794 throw new NoSuchElementException(); 795 796 HashMapEntry<K, V> entryToReturn = nextEntry; 797 HashMapEntry<K, V>[] tab = table; 798 HashMapEntry<K, V> next = entryToReturn.next; 799 while (next == null && nextIndex < tab.length) { 800 next = tab[nextIndex++]; 801 } 802 nextEntry = next; 803 return lastEntryReturned = entryToReturn; 804 } 805 806 public void remove() { 807 if (lastEntryReturned == null) 808 throw new IllegalStateException(); 809 if (modCount != expectedModCount) 810 throw new ConcurrentModificationException(); 811 HashMap.this.remove(lastEntryReturned.key); 812 lastEntryReturned = null; 813 expectedModCount = modCount; 814 } 815 } 816 817 private final class KeyIterator extends HashIterator 818 implements Iterator<K> { 819 public K next() { return nextEntry().key; } 820 } 821 822 private final class ValueIterator extends HashIterator 823 implements Iterator<V> { 824 public V next() { return nextEntry().value; } 825 } 826 827 private final class EntryIterator extends HashIterator 828 implements Iterator<Entry<K, V>> { 829 public Entry<K, V> next() { return nextEntry(); } 830 } 831 832 /** 833 * Returns true if this map contains the specified mapping. 834 */ 835 private boolean containsMapping(Object key, Object value) { 836 if (key == null) { 837 HashMapEntry<K, V> e = entryForNullKey; 838 return e != null && Objects.equal(value, e.value); 839 } 840 841 int hash = secondaryHash(key.hashCode()); 842 HashMapEntry<K, V>[] tab = table; 843 int index = hash & (tab.length - 1); 844 for (HashMapEntry<K, V> e = tab[index]; e != null; e = e.next) { 845 if (e.hash == hash && key.equals(e.key)) { 846 return Objects.equal(value, e.value); 847 } 848 } 849 return false; // No entry for key 850 } 851 852 /** 853 * Removes the mapping from key to value and returns true if this mapping 854 * exists; otherwise, returns does nothing and returns false. 855 */ 856 private boolean removeMapping(Object key, Object value) { 857 if (key == null) { 858 HashMapEntry<K, V> e = entryForNullKey; 859 if (e == null || !Objects.equal(value, e.value)) { 860 return false; 861 } 862 entryForNullKey = null; 863 modCount++; 864 size--; 865 postRemove(e); 866 return true; 867 } 868 869 int hash = secondaryHash(key.hashCode()); 870 HashMapEntry<K, V>[] tab = table; 871 int index = hash & (tab.length - 1); 872 for (HashMapEntry<K, V> e = tab[index], prev = null; 873 e != null; prev = e, e = e.next) { 874 if (e.hash == hash && key.equals(e.key)) { 875 if (!Objects.equal(value, e.value)) { 876 return false; // Map has wrong value for key 877 } 878 if (prev == null) { 879 tab[index] = e.next; 880 } else { 881 prev.next = e.next; 882 } 883 modCount++; 884 size--; 885 postRemove(e); 886 return true; 887 } 888 } 889 return false; // No entry for key 890 } 891 892 // Subclass (LinkedHashMap) overrides these for correct iteration order 893 Iterator<K> newKeyIterator() { return new KeyIterator(); } 894 Iterator<V> newValueIterator() { return new ValueIterator(); } 895 Iterator<Entry<K, V>> newEntryIterator() { return new EntryIterator(); } 896 897 private final class KeySet extends AbstractSet<K> { 898 public Iterator<K> iterator() { 899 return newKeyIterator(); 900 } 901 public int size() { 902 return size; 903 } 904 public boolean isEmpty() { 905 return size == 0; 906 } 907 public boolean contains(Object o) { 908 return containsKey(o); 909 } 910 public boolean remove(Object o) { 911 int oldSize = size; 912 HashMap.this.remove(o); 913 return size != oldSize; 914 } 915 public void clear() { 916 HashMap.this.clear(); 917 } 918 } 919 920 private final class Values extends AbstractCollection<V> { 921 public Iterator<V> iterator() { 922 return newValueIterator(); 923 } 924 public int size() { 925 return size; 926 } 927 public boolean isEmpty() { 928 return size == 0; 929 } 930 public boolean contains(Object o) { 931 return containsValue(o); 932 } 933 public void clear() { 934 HashMap.this.clear(); 935 } 936 } 937 938 private final class EntrySet extends AbstractSet<Entry<K, V>> { 939 public Iterator<Entry<K, V>> iterator() { 940 return newEntryIterator(); 941 } 942 public boolean contains(Object o) { 943 if (!(o instanceof Entry)) 944 return false; 945 Entry<?, ?> e = (Entry<?, ?>) o; 946 return containsMapping(e.getKey(), e.getValue()); 947 } 948 public boolean remove(Object o) { 949 if (!(o instanceof Entry)) 950 return false; 951 Entry<?, ?> e = (Entry<?, ?>)o; 952 return removeMapping(e.getKey(), e.getValue()); 953 } 954 public int size() { 955 return size; 956 } 957 public boolean isEmpty() { 958 return size == 0; 959 } 960 public void clear() { 961 HashMap.this.clear(); 962 } 963 } 964 965 /** 966 * Applies a supplemental hash function to a given hashCode, which defends 967 * against poor quality hash functions. This is critical because HashMap 968 * uses power-of-two length hash tables, that otherwise encounter collisions 969 * for hashCodes that do not differ in lower or upper bits. 970 */ 971 private static int secondaryHash(int h) { 972 // Doug Lea's supplemental hash function 973 h ^= (h >>> 20) ^ (h >>> 12); 974 return h ^ (h >>> 7) ^ (h >>> 4); 975 } 976 977 /** 978 * Returns the smallest power of two >= its argument, with several caveats: 979 * If the argument is negative but not Integer.MIN_VALUE, the method returns 980 * zero. If the argument is > 2^30 or equal to Integer.MIN_VALUE, the method 981 * returns Integer.MIN_VALUE. If the argument is zero, the method returns 982 * zero. 983 */ 984 private static int roundUpToPowerOfTwo(int i) { 985 i--; // If input is a power of two, shift its high-order bit right 986 987 // "Smear" the high-order bit all the way to the right 988 i |= i >>> 1; 989 i |= i >>> 2; 990 i |= i >>> 4; 991 i |= i >>> 8; 992 i |= i >>> 16; 993 994 return i + 1; 995 } 996 997 private static final long serialVersionUID = 362498820763181265L; 998 999 private static final ObjectStreamField[] serialPersistentFields = { 1000 new ObjectStreamField("loadFactor", float.class) 1001 }; 1002 1003 private void writeObject(ObjectOutputStream stream) throws IOException { 1004 // Emulate loadFactor field for other implementations to read 1005 ObjectOutputStream.PutField fields = stream.putFields(); 1006 fields.put("loadFactor", DEFAULT_LOAD_FACTOR); 1007 stream.writeFields(); 1008 1009 stream.writeInt(table.length); // Capacity 1010 stream.writeInt(size); 1011 for (Entry<K, V> e : entrySet()) { 1012 stream.writeObject(e.getKey()); 1013 stream.writeObject(e.getValue()); 1014 } 1015 } 1016 1017 private void readObject(ObjectInputStream stream) throws IOException, 1018 ClassNotFoundException { 1019 stream.defaultReadObject(); 1020 int capacity = stream.readInt(); 1021 if (capacity < 0) { 1022 throw new InvalidObjectException("Capacity: " + capacity); 1023 } 1024 if (capacity < MINIMUM_CAPACITY) { 1025 capacity = MINIMUM_CAPACITY; 1026 } else if (capacity > MAXIMUM_CAPACITY) { 1027 capacity = MAXIMUM_CAPACITY; 1028 } else { 1029 capacity = roundUpToPowerOfTwo(capacity); 1030 } 1031 makeTable(capacity); 1032 1033 int size = stream.readInt(); 1034 if (size < 0) { 1035 throw new InvalidObjectException("Size: " + size); 1036 } 1037 1038 init(); // Give subclass (LinkedHashMap) a chance to initialize itself 1039 for (int i = 0; i < size; i++) { 1040 @SuppressWarnings("unchecked") K key = (K) stream.readObject(); 1041 @SuppressWarnings("unchecked") V val = (V) stream.readObject(); 1042 constructorPut(key, val); 1043 } 1044 } 1045} 1046