1 7 8 package java.util; 9 import java.io.*; 10 11 100 101 public class HashMap<K,V> 102 extends AbstractMap <K,V> 103 implements Map <K,V>, Cloneable , Serializable 104 { 105 106 109 static final int DEFAULT_INITIAL_CAPACITY = 16; 110 111 116 static final int MAXIMUM_CAPACITY = 1 << 30; 117 118 121 static final float DEFAULT_LOAD_FACTOR = 0.75f; 122 123 126 transient Entry[] table; 127 128 131 transient int size; 132 133 137 int threshold; 138 139 144 final float loadFactor; 145 146 153 transient volatile int modCount; 154 155 164 public HashMap(int initialCapacity, float loadFactor) { 165 if (initialCapacity < 0) 166 throw new IllegalArgumentException ("Illegal initial capacity: " + 167 initialCapacity); 168 if (initialCapacity > MAXIMUM_CAPACITY) 169 initialCapacity = MAXIMUM_CAPACITY; 170 if (loadFactor <= 0 || Float.isNaN(loadFactor)) 171 throw new IllegalArgumentException ("Illegal load factor: " + 172 loadFactor); 173 174 int capacity = 1; 176 while (capacity < initialCapacity) 177 capacity <<= 1; 178 179 this.loadFactor = loadFactor; 180 threshold = (int)(capacity * loadFactor); 181 table = new Entry[capacity]; 182 init(); 183 } 184 185 192 public HashMap(int initialCapacity) { 193 this(initialCapacity, DEFAULT_LOAD_FACTOR); 194 } 195 196 200 public HashMap() { 201 this.loadFactor = DEFAULT_LOAD_FACTOR; 202 threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR); 203 table = new Entry[DEFAULT_INITIAL_CAPACITY]; 204 init(); 205 } 206 207 216 public HashMap(Map <? extends K, ? extends V> m) { 217 this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1, 218 DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR); 219 putAllForCreate(m); 220 } 221 222 224 231 void init() { 232 } 233 234 237 static final Object NULL_KEY = new Object (); 238 239 242 static <T> T maskNull(T key) { 243 return key == null ? (T)NULL_KEY : key; 244 } 245 246 249 static <T> T unmaskNull(T key) { 250 return (key == NULL_KEY ? null : key); 251 } 252 253 261 private static final boolean useNewHash; 262 static { useNewHash = false; } 263 264 private static int oldHash(int h) { 265 h += ~(h << 9); 266 h ^= (h >>> 14); 267 h += (h << 4); 268 h ^= (h >>> 10); 269 return h; 270 } 271 272 private static int newHash(int h) { 273 h ^= (h >>> 20) ^ (h >>> 12); 277 return h ^ (h >>> 7) ^ (h >>> 4); 278 } 279 280 287 static int hash(int h) { 288 return useNewHash ? newHash(h) : oldHash(h); 289 } 290 291 static int hash(Object key) { 292 return hash(key.hashCode()); 293 } 294 295 298 static boolean eq(Object x, Object y) { 299 return x == y || x.equals(y); 300 } 301 302 305 static int indexFor(int h, int length) { 306 return h & (length-1); 307 } 308 309 314 public int size() { 315 return size; 316 } 317 318 323 public boolean isEmpty() { 324 return size == 0; 325 } 326 327 340 public V get(Object key) { 341 if (key == null) 342 return getForNullKey(); 343 int hash = hash(key.hashCode()); 344 for (Entry<K,V> e = table[indexFor(hash, table.length)]; 345 e != null; 346 e = e.next) { 347 Object k; 348 if (e.hash == hash && ((k = e.key) == key || key.equals(k))) 349 return e.value; 350 } 351 return null; 352 } 353 354 private V getForNullKey() { 355 int hash = hash(NULL_KEY.hashCode()); 356 int i = indexFor(hash, table.length); 357 Entry<K,V> e = table[i]; 358 while (true) { 359 if (e == null) 360 return null; 361 if (e.key == NULL_KEY) 362 return e.value; 363 e = e.next; 364 } 365 } 366 367 375 public boolean containsKey(Object key) { 376 Object k = maskNull(key); 377 int hash = hash(k.hashCode()); 378 int i = indexFor(hash, table.length); 379 Entry e = table[i]; 380 while (e != null) { 381 if (e.hash == hash && eq(k, e.key)) 382 return true; 383 e = e.next; 384 } 385 return false; 386 } 387 388 393 Entry<K,V> getEntry(Object key) { 394 Object k = maskNull(key); 395 int hash = hash(k.hashCode()); 396 int i = indexFor(hash, table.length); 397 Entry<K,V> e = table[i]; 398 while (e != null && !(e.hash == hash && eq(k, e.key))) 399 e = e.next; 400 return e; 401 } 402 403 415 public V put(K key, V value) { 416 if (key == null) 417 return putForNullKey(value); 418 int hash = hash(key.hashCode()); 419 int i = indexFor(hash, table.length); 420 for (Entry<K,V> e = table[i]; e != null; e = e.next) { 421 Object k; 422 if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { 423 V oldValue = e.value; 424 e.value = value; 425 e.recordAccess(this); 426 return oldValue; 427 } 428 } 429 430 modCount++; 431 addEntry(hash, key, value, i); 432 return null; 433 } 434 435 private V putForNullKey(V value) { 436 int hash = hash(NULL_KEY.hashCode()); 437 int i = indexFor(hash, table.length); 438 439 for (Entry<K,V> e = table[i]; e != null; e = e.next) { 440 if (e.key == NULL_KEY) { 441 V oldValue = e.value; 442 e.value = value; 443 e.recordAccess(this); 444 return oldValue; 445 } 446 } 447 448 modCount++; 449 addEntry(hash, (K) NULL_KEY, value, i); 450 return null; 451 } 452 453 459 private void putForCreate(K key, V value) { 460 K k = maskNull(key); 461 int hash = hash(k.hashCode()); 462 int i = indexFor(hash, table.length); 463 464 469 for (Entry<K,V> e = table[i]; e != null; e = e.next) { 470 if (e.hash == hash && eq(k, e.key)) { 471 e.value = value; 472 return; 473 } 474 } 475 476 createEntry(hash, k, value, i); 477 } 478 479 void putAllForCreate(Map <? extends K, ? extends V> m) { 480 for (Iterator <? extends Map.Entry <? extends K, ? extends V>> i = m.entrySet().iterator(); i.hasNext(); ) { 481 Map.Entry <? extends K, ? extends V> e = i.next(); 482 putForCreate(e.getKey(), e.getValue()); 483 } 484 } 485 486 500 void resize(int newCapacity) { 501 Entry[] oldTable = table; 502 int oldCapacity = oldTable.length; 503 if (oldCapacity == MAXIMUM_CAPACITY) { 504 threshold = Integer.MAX_VALUE; 505 return; 506 } 507 508 Entry[] newTable = new Entry[newCapacity]; 509 transfer(newTable); 510 table = newTable; 511 threshold = (int)(newCapacity * loadFactor); 512 } 513 514 517 void transfer(Entry[] newTable) { 518 Entry[] src = table; 519 int newCapacity = newTable.length; 520 for (int j = 0; j < src.length; j++) { 521 Entry<K,V> e = src[j]; 522 if (e != null) { 523 src[j] = null; 524 do { 525 Entry<K,V> next = e.next; 526 int i = indexFor(e.hash, newCapacity); 527 e.next = newTable[i]; 528 newTable[i] = e; 529 e = next; 530 } while (e != null); 531 } 532 } 533 } 534 535 543 public void putAll(Map <? extends K, ? extends V> m) { 544 int numKeysToBeAdded = m.size(); 545 if (numKeysToBeAdded == 0) 546 return; 547 548 557 if (numKeysToBeAdded > threshold) { 558 int targetCapacity = (int)(numKeysToBeAdded / loadFactor + 1); 559 if (targetCapacity > MAXIMUM_CAPACITY) 560 targetCapacity = MAXIMUM_CAPACITY; 561 int newCapacity = table.length; 562 while (newCapacity < targetCapacity) 563 newCapacity <<= 1; 564 if (newCapacity > table.length) 565 resize(newCapacity); 566 } 567 568 for (Iterator <? extends Map.Entry <? extends K, ? extends V>> i = m.entrySet().iterator(); i.hasNext(); ) { 569 Map.Entry <? extends K, ? extends V> e = i.next(); 570 put(e.getKey(), e.getValue()); 571 } 572 } 573 574 583 public V remove(Object key) { 584 Entry<K,V> e = removeEntryForKey(key); 585 return (e == null ? null : e.value); 586 } 587 588 593 Entry<K,V> removeEntryForKey(Object key) { 594 Object k = maskNull(key); 595 int hash = hash(k.hashCode()); 596 int i = indexFor(hash, table.length); 597 Entry<K,V> prev = table[i]; 598 Entry<K,V> e = prev; 599 600 while (e != null) { 601 Entry<K,V> next = e.next; 602 if (e.hash == hash && eq(k, e.key)) { 603 modCount++; 604 size--; 605 if (prev == e) 606 table[i] = next; 607 else 608 prev.next = next; 609 e.recordRemoval(this); 610 return e; 611 } 612 prev = e; 613 e = next; 614 } 615 616 return e; 617 } 618 619 622 Entry<K,V> removeMapping(Object o) { 623 if (!(o instanceof Map.Entry )) 624 return null; 625 626 Map.Entry <K,V> entry = (Map.Entry <K,V>) o; 627 Object k = maskNull(entry.getKey()); 628 int hash = hash(k.hashCode()); 629 int i = indexFor(hash, table.length); 630 Entry<K,V> prev = table[i]; 631 Entry<K,V> e = prev; 632 633 while (e != null) { 634 Entry<K,V> next = e.next; 635 if (e.hash == hash && e.equals(entry)) { 636 modCount++; 637 size--; 638 if (prev == e) 639 table[i] = next; 640 else 641 prev.next = next; 642 e.recordRemoval(this); 643 return e; 644 } 645 prev = e; 646 e = next; 647 } 648 649 return e; 650 } 651 652 655 public void clear() { 656 modCount++; 657 Entry[] tab = table; 658 for (int i = 0; i < tab.length; i++) 659 tab[i] = null; 660 size = 0; 661 } 662 663 671 public boolean containsValue(Object value) { 672 if (value == null) 673 return containsNullValue(); 674 675 Entry[] tab = table; 676 for (int i = 0; i < tab.length ; i++) 677 for (Entry e = tab[i] ; e != null ; e = e.next) 678 if (value.equals(e.value)) 679 return true; 680 return false; 681 } 682 683 686 private boolean containsNullValue() { 687 Entry[] tab = table; 688 for (int i = 0; i < tab.length ; i++) 689 for (Entry e = tab[i] ; e != null ; e = e.next) 690 if (e.value == null) 691 return true; 692 return false; 693 } 694 695 701 public Object clone() { 702 HashMap <K,V> result = null; 703 try { 704 result = (HashMap <K,V>)super.clone(); 705 } catch (CloneNotSupportedException e) { 706 } 708 result.table = new Entry[table.length]; 709 result.entrySet = null; 710 result.modCount = 0; 711 result.size = 0; 712 result.init(); 713 result.putAllForCreate(this); 714 715 return result; 716 } 717 718 static class Entry<K,V> implements Map.Entry <K,V> { 719 final K key; 720 V value; 721 final int hash; 722 Entry<K,V> next; 723 724 727 Entry(int h, K k, V v, Entry<K,V> n) { 728 value = v; 729 next = n; 730 key = k; 731 hash = h; 732 } 733 734 public K getKey() { 735 return HashMap.<K>unmaskNull(key); 736 } 737 738 public V getValue() { 739 return value; 740 } 741 742 public V setValue(V newValue) { 743 V oldValue = value; 744 value = newValue; 745 return oldValue; 746 } 747 748 public boolean equals(Object o) { 749 if (!(o instanceof Map.Entry )) 750 return false; 751 Map.Entry e = (Map.Entry )o; 752 Object k1 = getKey(); 753 Object k2 = e.getKey(); 754 if (k1 == k2 || (k1 != null && k1.equals(k2))) { 755 Object v1 = getValue(); 756 Object v2 = e.getValue(); 757 if (v1 == v2 || (v1 != null && v1.equals(v2))) 758 return true; 759 } 760 return false; 761 } 762 763 public int hashCode() { 764 return (key==NULL_KEY ? 0 : key.hashCode()) ^ 765 (value==null ? 0 : value.hashCode()); 766 } 767 768 public String toString() { 769 return getKey() + "=" + getValue(); 770 } 771 772 777 void recordAccess(HashMap <K,V> m) { 778 } 779 780 784 void recordRemoval(HashMap <K,V> m) { 785 } 786 } 787 788 795 void addEntry(int hash, K key, V value, int bucketIndex) { 796 Entry<K,V> e = table[bucketIndex]; 797 table[bucketIndex] = new Entry<K,V>(hash, key, value, e); 798 if (size++ >= threshold) 799 resize(2 * table.length); 800 } 801 802 810 void createEntry(int hash, K key, V value, int bucketIndex) { 811 Entry<K,V> e = table[bucketIndex]; 812 table[bucketIndex] = new Entry<K,V>(hash, key, value, e); 813 size++; 814 } 815 816 private abstract class HashIterator<E> implements Iterator <E> { 817 Entry<K,V> next; int expectedModCount; int index; Entry<K,V> current; 822 HashIterator() { 823 expectedModCount = modCount; 824 Entry[] t = table; 825 int i = t.length; 826 Entry<K,V> n = null; 827 if (size != 0) { while (i > 0 && (n = t[--i]) == null) 829 ; 830 } 831 next = n; 832 index = i; 833 } 834 835 public boolean hasNext() { 836 return next != null; 837 } 838 839 Entry<K,V> nextEntry() { 840 if (modCount != expectedModCount) 841 throw new ConcurrentModificationException (); 842 Entry<K,V> e = next; 843 if (e == null) 844 throw new NoSuchElementException (); 845 846 Entry<K,V> n = e.next; 847 Entry[] t = table; 848 int i = index; 849 while (n == null && i > 0) 850 n = t[--i]; 851 index = i; 852 next = n; 853 return current = e; 854 } 855 856 public void remove() { 857 if (current == null) 858 throw new IllegalStateException (); 859 if (modCount != expectedModCount) 860 throw new ConcurrentModificationException (); 861 Object k = current.key; 862 current = null; 863 HashMap.this.removeEntryForKey(k); 864 expectedModCount = modCount; 865 } 866 867 } 868 869 private class ValueIterator extends HashIterator<V> { 870 public V next() { 871 return nextEntry().value; 872 } 873 } 874 875 private class KeyIterator extends HashIterator<K> { 876 public K next() { 877 return nextEntry().getKey(); 878 } 879 } 880 881 private class EntryIterator extends HashIterator<Map.Entry <K,V>> { 882 public Map.Entry <K,V> next() { 883 return nextEntry(); 884 } 885 } 886 887 Iterator <K> newKeyIterator() { 889 return new KeyIterator(); 890 } 891 Iterator <V> newValueIterator() { 892 return new ValueIterator(); 893 } 894 Iterator <Map.Entry <K,V>> newEntryIterator() { 895 return new EntryIterator(); 896 } 897 898 899 901 private transient Set <Map.Entry <K,V>> entrySet = null; 902 903 914 public Set <K> keySet() { 915 Set <K> ks = keySet; 916 return (ks != null ? ks : (keySet = new KeySet())); 917 } 918 919 private class KeySet extends AbstractSet <K> { 920 public Iterator <K> iterator() { 921 return newKeyIterator(); 922 } 923 public int size() { 924 return size; 925 } 926 public boolean contains(Object o) { 927 return containsKey(o); 928 } 929 public boolean remove(Object o) { 930 return HashMap.this.removeEntryForKey(o) != null; 931 } 932 public void clear() { 933 HashMap.this.clear(); 934 } 935 } 936 937 948 public Collection <V> values() { 949 Collection <V> vs = values; 950 return (vs != null ? vs : (values = new Values())); 951 } 952 953 private class Values extends AbstractCollection <V> { 954 public Iterator <V> iterator() { 955 return newValueIterator(); 956 } 957 public int size() { 958 return size; 959 } 960 public boolean contains(Object o) { 961 return containsValue(o); 962 } 963 public void clear() { 964 HashMap.this.clear(); 965 } 966 } 967 968 981 public Set <Map.Entry <K,V>> entrySet() { 982 Set <Map.Entry <K,V>> es = entrySet; 983 return (es != null ? es : (entrySet = (Set <Map.Entry <K,V>>) (Set ) new EntrySet())); 984 } 985 986 private class EntrySet extends AbstractSet { 987 public Iterator iterator() { 988 return newEntryIterator(); 989 } 990 public boolean contains(Object o) { 991 if (!(o instanceof Map.Entry )) 992 return false; 993 Map.Entry <K,V> e = (Map.Entry <K,V>) o; 994 Entry<K,V> candidate = getEntry(e.getKey()); 995 return candidate != null && candidate.equals(e); 996 } 997 public boolean remove(Object o) { 998 return removeMapping(o) != null; 999 } 1000 public int size() { 1001 return size; 1002 } 1003 public void clear() { 1004 HashMap.this.clear(); 1005 } 1006 } 1007 1008 1021 private void writeObject(java.io.ObjectOutputStream s) 1022 throws IOException 1023 { 1024 Iterator <Map.Entry <K,V>> i = entrySet().iterator(); 1025 1026 s.defaultWriteObject(); 1028 1029 s.writeInt(table.length); 1031 1032 s.writeInt(size); 1034 1035 while (i.hasNext()) { 1037 Map.Entry <K,V> e = i.next(); 1038 s.writeObject(e.getKey()); 1039 s.writeObject(e.getValue()); 1040 } 1041 } 1042 1043 private static final long serialVersionUID = 362498820763181265L; 1044 1045 1049 private void readObject(java.io.ObjectInputStream s) 1050 throws IOException, ClassNotFoundException 1051 { 1052 s.defaultReadObject(); 1054 1055 int numBuckets = s.readInt(); 1057 table = new Entry[numBuckets]; 1058 1059 init(); 1061 int size = s.readInt(); 1063 1064 for (int i=0; i<size; i++) { 1066 K key = (K) s.readObject(); 1067 V value = (V) s.readObject(); 1068 putForCreate(key, value); 1069 } 1070 } 1071 1072 int capacity() { return table.length; } 1074 float loadFactor() { return loadFactor; } 1075} 1076 | Popular Tags |