1 7 8 package java.util; 9 import java.io.*; 10 11 105 public class Hashtable<K,V> 106 extends Dictionary <K,V> 107 implements Map <K,V>, Cloneable , java.io.Serializable { 108 109 112 private transient Entry[] table; 113 114 117 private transient int count; 118 119 125 private int threshold; 126 127 132 private float loadFactor; 133 134 141 private transient int modCount = 0; 142 143 144 private static final long serialVersionUID = 1421746759512286392L; 145 146 155 public Hashtable(int initialCapacity, float loadFactor) { 156 if (initialCapacity < 0) 157 throw new IllegalArgumentException ("Illegal Capacity: "+ 158 initialCapacity); 159 if (loadFactor <= 0 || Float.isNaN(loadFactor)) 160 throw new IllegalArgumentException ("Illegal Load: "+loadFactor); 161 162 if (initialCapacity==0) 163 initialCapacity = 1; 164 this.loadFactor = loadFactor; 165 table = new Entry[initialCapacity]; 166 threshold = (int)(initialCapacity * loadFactor); 167 } 168 169 177 public Hashtable(int initialCapacity) { 178 this(initialCapacity, 0.75f); 179 } 180 181 185 public Hashtable() { 186 this(11, 0.75f); 187 } 188 189 199 public Hashtable(Map <? extends K, ? extends V> t) { 200 this(Math.max(2*t.size(), 11), 0.75f); 201 putAll(t); 202 } 203 204 209 public synchronized int size() { 210 return count; 211 } 212 213 219 public synchronized boolean isEmpty() { 220 return count == 0; 221 } 222 223 232 public synchronized Enumeration <K> keys() { 233 return this.<K>getEnumeration(KEYS); 234 } 235 236 247 public synchronized Enumeration <V> elements() { 248 return this.<V>getEnumeration(VALUES); 249 } 250 251 269 public synchronized boolean contains(Object value) { 270 if (value == null) { 271 throw new NullPointerException (); 272 } 273 274 Entry tab[] = table; 275 for (int i = tab.length ; i-- > 0 ;) { 276 for (Entry<K,V> e = tab[i] ; e != null ; e = e.next) { 277 if (e.value.equals(value)) { 278 return true; 279 } 280 } 281 } 282 return false; 283 } 284 285 298 public boolean containsValue(Object value) { 299 return contains(value); 300 } 301 302 312 public synchronized boolean containsKey(Object key) { 313 Entry tab[] = table; 314 int hash = key.hashCode(); 315 int index = (hash & 0x7FFFFFFF) % tab.length; 316 for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) { 317 if ((e.hash == hash) && e.key.equals(key)) { 318 return true; 319 } 320 } 321 return false; 322 } 323 324 334 public synchronized V get(Object key) { 335 Entry tab[] = table; 336 int hash = key.hashCode(); 337 int index = (hash & 0x7FFFFFFF) % tab.length; 338 for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) { 339 if ((e.hash == hash) && e.key.equals(key)) { 340 return e.value; 341 } 342 } 343 return null; 344 } 345 346 353 protected void rehash() { 354 int oldCapacity = table.length; 355 Entry[] oldMap = table; 356 357 int newCapacity = oldCapacity * 2 + 1; 358 Entry[] newMap = new Entry[newCapacity]; 359 360 modCount++; 361 threshold = (int)(newCapacity * loadFactor); 362 table = newMap; 363 364 for (int i = oldCapacity ; i-- > 0 ;) { 365 for (Entry<K,V> old = oldMap[i] ; old != null ; ) { 366 Entry<K,V> e = old; 367 old = old.next; 368 369 int index = (e.hash & 0x7FFFFFFF) % newCapacity; 370 e.next = newMap[index]; 371 newMap[index] = e; 372 } 373 } 374 } 375 376 393 public synchronized V put(K key, V value) { 394 if (value == null) { 396 throw new NullPointerException (); 397 } 398 399 Entry tab[] = table; 401 int hash = key.hashCode(); 402 int index = (hash & 0x7FFFFFFF) % tab.length; 403 for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) { 404 if ((e.hash == hash) && e.key.equals(key)) { 405 V old = e.value; 406 e.value = value; 407 return old; 408 } 409 } 410 411 modCount++; 412 if (count >= threshold) { 413 rehash(); 415 416 tab = table; 417 index = (hash & 0x7FFFFFFF) % tab.length; 418 } 419 420 Entry<K,V> e = tab[index]; 422 tab[index] = new Entry<K,V>(hash, key, value, e); 423 count++; 424 return null; 425 } 426 427 436 public synchronized V remove(Object key) { 437 Entry tab[] = table; 438 int hash = key.hashCode(); 439 int index = (hash & 0x7FFFFFFF) % tab.length; 440 for (Entry<K,V> e = tab[index], prev = null ; e != null ; prev = e, e = e.next) { 441 if ((e.hash == hash) && e.key.equals(key)) { 442 modCount++; 443 if (prev != null) { 444 prev.next = e.next; 445 } else { 446 tab[index] = e.next; 447 } 448 count--; 449 V oldValue = e.value; 450 e.value = null; 451 return oldValue; 452 } 453 } 454 return null; 455 } 456 457 466 public synchronized void putAll(Map <? extends K, ? extends V> t) { 467 Iterator <? extends Map.Entry <? extends K, ? extends V>> i = t.entrySet().iterator(); 468 while (i.hasNext()) { 469 Map.Entry <? extends K, ? extends V> e = i.next(); 470 put(e.getKey(), e.getValue()); 471 } 472 } 473 474 477 public synchronized void clear() { 478 Entry tab[] = table; 479 modCount++; 480 for (int index = tab.length; --index >= 0; ) 481 tab[index] = null; 482 count = 0; 483 } 484 485 492 public synchronized Object clone() { 493 try { 494 Hashtable <K,V> t = (Hashtable <K,V>) super.clone(); 495 t.table = new Entry[table.length]; 496 for (int i = table.length ; i-- > 0 ; ) { 497 t.table[i] = (table[i] != null) 498 ? (Entry<K,V>) table[i].clone() : null; 499 } 500 t.keySet = null; 501 t.entrySet = null; 502 t.values = null; 503 t.modCount = 0; 504 return t; 505 } catch (CloneNotSupportedException e) { 506 throw new InternalError (); 508 } 509 } 510 511 522 public synchronized String toString() { 523 int max = size() - 1; 524 StringBuffer buf = new StringBuffer (); 525 Iterator <Map.Entry <K,V>> it = entrySet().iterator(); 526 527 buf.append("{"); 528 for (int i = 0; i <= max; i++) { 529 Map.Entry <K,V> e = it.next(); 530 K key = e.getKey(); 531 V value = e.getValue(); 532 buf.append((key == this ? "(this Map)" : (""+key)) + "=" + 533 (value == this ? "(this Map)" : (""+value))); 534 535 if (i < max) 536 buf.append(", "); 537 } 538 buf.append("}"); 539 return buf.toString(); 540 } 541 542 543 private <T> Enumeration <T> getEnumeration(int type) { 544 if (count == 0) { 545 return (Enumeration <T>)emptyEnumerator; 546 } else { 547 return new Enumerator<T>(type, false); 548 } 549 } 550 551 private <T> Iterator <T> getIterator(int type) { 552 if (count == 0) { 553 return (Iterator <T>) emptyIterator; 554 } else { 555 return new Enumerator<T>(type, true); 556 } 557 } 558 559 561 566 private transient volatile Set <K> keySet = null; 567 private transient volatile Set <Map.Entry <K,V>> entrySet = null; 568 private transient volatile Collection <V> values = null; 569 570 580 public Set <K> keySet() { 581 if (keySet == null) 582 keySet = Collections.synchronizedSet(new KeySet(), this); 583 return keySet; 584 } 585 586 private class KeySet extends AbstractSet <K> { 587 public Iterator <K> iterator() { 588 return getIterator(KEYS); 589 } 590 public int size() { 591 return count; 592 } 593 public boolean contains(Object o) { 594 return containsKey(o); 595 } 596 public boolean remove(Object o) { 597 return Hashtable.this.remove(o) != null; 598 } 599 public void clear() { 600 Hashtable.this.clear(); 601 } 602 } 603 604 616 public Set <Map.Entry <K,V>> entrySet() { 617 if (entrySet==null) 618 entrySet = Collections.synchronizedSet(new EntrySet(), this); 619 return entrySet; 620 } 621 622 private class EntrySet extends AbstractSet { 623 public Iterator iterator() { 624 return getIterator(ENTRIES); 625 } 626 627 public boolean add(Object o) { 628 return super.add(o); 629 } 630 631 public boolean contains(Object o) { 632 if (!(o instanceof Map.Entry )) 633 return false; 634 Map.Entry entry = (Map.Entry )o; 635 Object key = entry.getKey(); 636 Entry[] tab = table; 637 int hash = key.hashCode(); 638 int index = (hash & 0x7FFFFFFF) % tab.length; 639 640 for (Entry e = tab[index]; e != null; e = e.next) 641 if (e.hash==hash && e.equals(entry)) 642 return true; 643 return false; 644 } 645 646 public boolean remove(Object o) { 647 if (!(o instanceof Map.Entry )) 648 return false; 649 Map.Entry <K,V> entry = (Map.Entry <K,V>) o; 650 K key = entry.getKey(); 651 Entry[] tab = table; 652 int hash = key.hashCode(); 653 int index = (hash & 0x7FFFFFFF) % tab.length; 654 655 for (Entry<K,V> e = tab[index], prev = null; e != null; 656 prev = e, e = e.next) { 657 if (e.hash==hash && e.equals(entry)) { 658 modCount++; 659 if (prev != null) 660 prev.next = e.next; 661 else 662 tab[index] = e.next; 663 664 count--; 665 e.value = null; 666 return true; 667 } 668 } 669 return false; 670 } 671 672 public int size() { 673 return count; 674 } 675 676 public void clear() { 677 Hashtable.this.clear(); 678 } 679 } 680 681 691 public Collection <V> values() { 692 if (values==null) 693 values = Collections.synchronizedCollection(new ValueCollection(), 694 this); 695 return values; 696 } 697 698 private class ValueCollection extends AbstractCollection <V> { 699 public Iterator <V> iterator() { 700 return getIterator(VALUES); 701 } 702 public int size() { 703 return count; 704 } 705 public boolean contains(Object o) { 706 return containsValue(o); 707 } 708 public void clear() { 709 Hashtable.this.clear(); 710 } 711 } 712 713 715 724 public synchronized boolean equals(Object o) { 725 if (o == this) 726 return true; 727 728 if (!(o instanceof Map )) 729 return false; 730 Map <K,V> t = (Map <K,V>) o; 731 if (t.size() != size()) 732 return false; 733 734 try { 735 Iterator <Map.Entry <K,V>> i = entrySet().iterator(); 736 while (i.hasNext()) { 737 Map.Entry <K,V> e = i.next(); 738 K key = e.getKey(); 739 V value = e.getValue(); 740 if (value == null) { 741 if (!(t.get(key)==null && t.containsKey(key))) 742 return false; 743 } else { 744 if (!value.equals(t.get(key))) 745 return false; 746 } 747 } 748 } catch(ClassCastException unused) { 749 return false; 750 } catch(NullPointerException unused) { 751 return false; 752 } 753 754 return true; 755 } 756 757 764 public synchronized int hashCode() { 765 775 int h = 0; 776 if (count == 0 || loadFactor < 0) 777 return h; 779 loadFactor = -loadFactor; Entry[] tab = table; 781 for (int i = 0; i < tab.length; i++) 782 for (Entry e = tab[i]; e != null; e = e.next) 783 h += e.key.hashCode() ^ e.value.hashCode(); 784 loadFactor = -loadFactor; 786 return h; 787 } 788 789 799 private synchronized void writeObject(java.io.ObjectOutputStream s) 800 throws IOException 801 { 802 s.defaultWriteObject(); 804 805 s.writeInt(table.length); 807 s.writeInt(count); 808 for (int index = table.length-1; index >= 0; index--) { 809 Entry entry = table[index]; 810 811 while (entry != null) { 812 s.writeObject(entry.key); 813 s.writeObject(entry.value); 814 entry = entry.next; 815 } 816 } 817 } 818 819 822 private void readObject(java.io.ObjectInputStream s) 823 throws IOException, ClassNotFoundException 824 { 825 s.defaultReadObject(); 827 828 int origlength = s.readInt(); 830 int elements = s.readInt(); 831 832 int length = (int)(elements * loadFactor) + (elements / 20) + 3; 837 if (length > elements && (length & 1) == 0) 838 length--; 839 if (origlength > 0 && length > origlength) 840 length = origlength; 841 842 table = new Entry[length]; 843 count = 0; 844 845 for (; elements > 0; elements--) { 847 K key = (K)s.readObject(); 848 V value = (V)s.readObject(); 849 reconstitutionPut(key, value); 851 } 852 } 853 854 865 private void reconstitutionPut(K key, V value) 866 throws StreamCorruptedException 867 { 868 if (value == null) { 869 throw new java.io.StreamCorruptedException (); 870 } 871 Entry[] tab = table; 874 int hash = key.hashCode(); 875 int index = (hash & 0x7FFFFFFF) % tab.length; 876 for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) { 877 if ((e.hash == hash) && e.key.equals(key)) { 878 throw new java.io.StreamCorruptedException (); 879 } 880 } 881 Entry<K,V> e = tab[index]; 883 tab[index] = new Entry<K,V>(hash, key, value, e); 884 count++; 885 } 886 887 890 private static class Entry<K,V> implements Map.Entry <K,V> { 891 int hash; 892 K key; 893 V value; 894 Entry<K,V> next; 895 896 protected Entry(int hash, K key, V value, Entry<K,V> next) { 897 this.hash = hash; 898 this.key = key; 899 this.value = value; 900 this.next = next; 901 } 902 903 protected Object clone() { 904 return new Entry<K,V>(hash, key, value, 905 (next==null ? null : (Entry<K,V>) next.clone())); 906 } 907 908 910 public K getKey() { 911 return key; 912 } 913 914 public V getValue() { 915 return value; 916 } 917 918 public V setValue(V value) { 919 if (value == null) 920 throw new NullPointerException (); 921 922 V oldValue = this.value; 923 this.value = value; 924 return oldValue; 925 } 926 927 public boolean equals(Object o) { 928 if (!(o instanceof Map.Entry )) 929 return false; 930 Map.Entry e = (Map.Entry )o; 931 932 return (key==null ? e.getKey()==null : key.equals(e.getKey())) && 933 (value==null ? e.getValue()==null : value.equals(e.getValue())); 934 } 935 936 public int hashCode() { 937 return hash ^ (value==null ? 0 : value.hashCode()); 938 } 939 940 public String toString() { 941 return key.toString()+"="+value.toString(); 942 } 943 } 944 945 private static final int KEYS = 0; 947 private static final int VALUES = 1; 948 private static final int ENTRIES = 2; 949 950 957 private class Enumerator<T> implements Enumeration <T>, Iterator <T> { 958 Entry[] table = Hashtable.this.table; 959 int index = table.length; 960 Entry<K,V> entry = null; 961 Entry<K,V> lastReturned = null; 962 int type; 963 964 968 boolean iterator; 969 970 975 protected int expectedModCount = modCount; 976 977 Enumerator(int type, boolean iterator) { 978 this.type = type; 979 this.iterator = iterator; 980 } 981 982 public boolean hasMoreElements() { 983 Entry<K,V> e = entry; 984 int i = index; 985 Entry[] t = table; 986 987 while (e == null && i > 0) { 988 e = t[--i]; 989 } 990 entry = e; 991 index = i; 992 return e != null; 993 } 994 995 public T nextElement() { 996 Entry<K,V> et = entry; 997 int i = index; 998 Entry[] t = table; 999 1000 while (et == null && i > 0) { 1001 et = t[--i]; 1002 } 1003 entry = et; 1004 index = i; 1005 if (et != null) { 1006 Entry<K,V> e = lastReturned = entry; 1007 entry = e.next; 1008 return type == KEYS ? (T)e.key : (type == VALUES ? (T)e.value : (T)e); 1009 } 1010 throw new NoSuchElementException ("Hashtable Enumerator"); 1011 } 1012 1013 public boolean hasNext() { 1015 return hasMoreElements(); 1016 } 1017 1018 public T next() { 1019 if (modCount != expectedModCount) 1020 throw new ConcurrentModificationException (); 1021 return nextElement(); 1022 } 1023 1024 public void remove() { 1025 if (!iterator) 1026 throw new UnsupportedOperationException (); 1027 if (lastReturned == null) 1028 throw new IllegalStateException ("Hashtable Enumerator"); 1029 if (modCount != expectedModCount) 1030 throw new ConcurrentModificationException (); 1031 1032 synchronized(Hashtable.this) { 1033 Entry[] tab = Hashtable.this.table; 1034 int index = (lastReturned.hash & 0x7FFFFFFF) % tab.length; 1035 1036 for (Entry<K,V> e = tab[index], prev = null; e != null; 1037 prev = e, e = e.next) { 1038 if (e == lastReturned) { 1039 modCount++; 1040 expectedModCount++; 1041 if (prev == null) 1042 tab[index] = e.next; 1043 else 1044 prev.next = e.next; 1045 count--; 1046 lastReturned = null; 1047 return; 1048 } 1049 } 1050 throw new ConcurrentModificationException (); 1051 } 1052 } 1053 } 1054 1055 1056 private static Enumeration emptyEnumerator = new EmptyEnumerator(); 1057 private static Iterator emptyIterator = new EmptyIterator(); 1058 1059 1063 private static class EmptyEnumerator implements Enumeration <Object > { 1064 1065 EmptyEnumerator() { 1066 } 1067 1068 public boolean hasMoreElements() { 1069 return false; 1070 } 1071 1072 public Object nextElement() { 1073 throw new NoSuchElementException ("Hashtable Enumerator"); 1074 } 1075 } 1076 1077 1078 1081 private static class EmptyIterator implements Iterator <Object > { 1082 1083 EmptyIterator() { 1084 } 1085 1086 public boolean hasNext() { 1087 return false; 1088 } 1089 1090 public Object next() { 1091 throw new NoSuchElementException ("Hashtable Iterator"); 1092 } 1093 1094 public void remove() { 1095 throw new IllegalStateException ("Hashtable Iterator"); 1096 } 1097 1098 } 1099 1100} 1101 | Popular Tags |