src/share/classes/java/util/Hashtable.java

Print this page
rev 5028 : 7126277: alternative hashing


 112  *
 113  * @author  Arthur van Hoff
 114  * @author  Josh Bloch
 115  * @author  Neal Gafter
 116  * @see     Object#equals(java.lang.Object)
 117  * @see     Object#hashCode()
 118  * @see     Hashtable#rehash()
 119  * @see     Collection
 120  * @see     Map
 121  * @see     HashMap
 122  * @see     TreeMap
 123  * @since JDK1.0
 124  */
 125 public class Hashtable<K,V>
 126     extends Dictionary<K,V>
 127     implements Map<K,V>, Cloneable, java.io.Serializable {
 128 
 129     /**
 130      * The hash table data.
 131      */
 132     private transient Entry[] table;
 133 
 134     /**
 135      * The total number of entries in the hash table.
 136      */
 137     private transient int count;
 138 
 139     /**
 140      * The table is rehashed when its size exceeds this threshold.  (The
 141      * value of this field is (int)(capacity * loadFactor).)
 142      *
 143      * @serial
 144      */
 145     private int threshold;
 146 
 147     /**
 148      * The load factor for the hashtable.
 149      *
 150      * @serial
 151      */
 152     private float loadFactor;
 153 
 154     /**
 155      * The number of times this Hashtable has been structurally modified
 156      * Structural modifications are those that change the number of entries in
 157      * the Hashtable or otherwise modify its internal structure (e.g.,
 158      * rehash).  This field is used to make iterators on Collection-views of
 159      * the Hashtable fail-fast.  (See ConcurrentModificationException).
 160      */
 161     private transient int modCount = 0;
 162 
 163     /** use serialVersionUID from JDK 1.0.2 for interoperability */
 164     private static final long serialVersionUID = 1421746759512286392L;
 165 
 166     /**






























































































 167      * Constructs a new, empty hashtable with the specified initial
 168      * capacity and the specified load factor.
 169      *
 170      * @param      initialCapacity   the initial capacity of the hashtable.
 171      * @param      loadFactor        the load factor of the hashtable.
 172      * @exception  IllegalArgumentException  if the initial capacity is less
 173      *             than zero, or if the load factor is nonpositive.
 174      */
 175     public Hashtable(int initialCapacity, float loadFactor) {
 176         if (initialCapacity < 0)
 177             throw new IllegalArgumentException("Illegal Capacity: "+
 178                                                initialCapacity);
 179         if (loadFactor <= 0 || Float.isNaN(loadFactor))
 180             throw new IllegalArgumentException("Illegal Load: "+loadFactor);
 181 
 182         if (initialCapacity==0)
 183             initialCapacity = 1;
 184         this.loadFactor = loadFactor;
 185         table = new Entry[initialCapacity];
 186         threshold = (int)(initialCapacity * loadFactor);


 187     }
 188 
 189     /**
 190      * Constructs a new, empty hashtable with the specified initial capacity
 191      * and default load factor (0.75).
 192      *
 193      * @param     initialCapacity   the initial capacity of the hashtable.
 194      * @exception IllegalArgumentException if the initial capacity is less
 195      *              than zero.
 196      */
 197     public Hashtable(int initialCapacity) {
 198         this(initialCapacity, 0.75f);
 199     }
 200 
 201     /**
 202      * Constructs a new, empty hashtable with a default initial capacity (11)
 203      * and load factor (0.75).
 204      */
 205     public Hashtable() {
 206         this(11, 0.75f);


 310      *         specified value
 311      * @throws NullPointerException  if the value is <code>null</code>
 312      * @since 1.2
 313      */
 314     public boolean containsValue(Object value) {
 315         return contains(value);
 316     }
 317 
 318     /**
 319      * Tests if the specified object is a key in this hashtable.
 320      *
 321      * @param   key   possible key
 322      * @return  <code>true</code> if and only if the specified object
 323      *          is a key in this hashtable, as determined by the
 324      *          <tt>equals</tt> method; <code>false</code> otherwise.
 325      * @throws  NullPointerException  if the key is <code>null</code>
 326      * @see     #contains(Object)
 327      */
 328     public synchronized boolean containsKey(Object key) {
 329         Entry tab[] = table;
 330         int hash = key.hashCode();
 331         int index = (hash & 0x7FFFFFFF) % tab.length;
 332         for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {
 333             if ((e.hash == hash) && e.key.equals(key)) {
 334                 return true;
 335             }
 336         }
 337         return false;
 338     }
 339 
 340     /**
 341      * Returns the value to which the specified key is mapped,
 342      * or {@code null} if this map contains no mapping for the key.
 343      *
 344      * <p>More formally, if this map contains a mapping from a key
 345      * {@code k} to a value {@code v} such that {@code (key.equals(k))},
 346      * then this method returns {@code v}; otherwise it returns
 347      * {@code null}.  (There can be at most one such mapping.)
 348      *
 349      * @param key the key whose associated value is to be returned
 350      * @return the value to which the specified key is mapped, or
 351      *         {@code null} if this map contains no mapping for the key
 352      * @throws NullPointerException if the specified key is null
 353      * @see     #put(Object, Object)
 354      */
 355     public synchronized V get(Object key) {
 356         Entry tab[] = table;
 357         int hash = key.hashCode();
 358         int index = (hash & 0x7FFFFFFF) % tab.length;
 359         for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {
 360             if ((e.hash == hash) && e.key.equals(key)) {
 361                 return e.value;
 362             }
 363         }
 364         return null;
 365     }
 366 
 367     /**
 368      * The maximum size of array to allocate.
 369      * Some VMs reserve some header words in an array.
 370      * Attempts to allocate larger arrays may result in
 371      * OutOfMemoryError: Requested array size exceeds VM limit
 372      */
 373     private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
 374 
 375     /**
 376      * Increases the capacity of and internally reorganizes this
 377      * hashtable, in order to accommodate and access its entries more
 378      * efficiently.  This method is called automatically when the
 379      * number of keys in the hashtable exceeds this hashtable's capacity
 380      * and load factor.
 381      */
 382     protected void rehash() {
 383         int oldCapacity = table.length;
 384         Entry[] oldMap = table;
 385 
 386         // overflow-conscious code
 387         int newCapacity = (oldCapacity << 1) + 1;
 388         if (newCapacity - MAX_ARRAY_SIZE > 0) {
 389             if (oldCapacity == MAX_ARRAY_SIZE)
 390                 // Keep running with MAX_ARRAY_SIZE buckets
 391                 return;
 392             newCapacity = MAX_ARRAY_SIZE;
 393         }
 394         Entry[] newMap = new Entry[newCapacity];
 395 
 396         modCount++;
 397         threshold = (int)(newCapacity * loadFactor);





 398         table = newMap;
 399 
 400         for (int i = oldCapacity ; i-- > 0 ;) {
 401             for (Entry<K,V> old = oldMap[i] ; old != null ; ) {
 402                 Entry<K,V> e = old;
 403                 old = old.next;
 404 



 405                 int index = (e.hash & 0x7FFFFFFF) % newCapacity;
 406                 e.next = newMap[index];
 407                 newMap[index] = e;
 408             }
 409         }
 410     }
 411 
 412     /**
 413      * Maps the specified <code>key</code> to the specified
 414      * <code>value</code> in this hashtable. Neither the key nor the
 415      * value can be <code>null</code>. <p>
 416      *
 417      * The value can be retrieved by calling the <code>get</code> method
 418      * with a key that is equal to the original key.
 419      *
 420      * @param      key     the hashtable key
 421      * @param      value   the value
 422      * @return     the previous value of the specified key in this hashtable,
 423      *             or <code>null</code> if it did not have one
 424      * @exception  NullPointerException  if the key or value is
 425      *               <code>null</code>
 426      * @see     Object#equals(Object)
 427      * @see     #get(Object)
 428      */
 429     public synchronized V put(K key, V value) {
 430         // Make sure the value is not null
 431         if (value == null) {
 432             throw new NullPointerException();
 433         }
 434 
 435         // Makes sure the key is not already in the hashtable.
 436         Entry tab[] = table;
 437         int hash = key.hashCode();
 438         int index = (hash & 0x7FFFFFFF) % tab.length;
 439         for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {
 440             if ((e.hash == hash) && e.key.equals(key)) {
 441                 V old = e.value;
 442                 e.value = value;
 443                 return old;
 444             }
 445         }
 446 
 447         modCount++;
 448         if (count >= threshold) {
 449             // Rehash the table if the threshold is exceeded
 450             rehash();
 451 
 452             tab = table;

 453             index = (hash & 0x7FFFFFFF) % tab.length;
 454         }
 455 
 456         // Creates the new entry.
 457         Entry<K,V> e = tab[index];
 458         tab[index] = new Entry<>(hash, key, value, e);
 459         count++;
 460         return null;
 461     }
 462 
 463     /**
 464      * Removes the key (and its corresponding value) from this
 465      * hashtable. This method does nothing if the key is not in the hashtable.
 466      *
 467      * @param   key   the key that needs to be removed
 468      * @return  the value to which the key had been mapped in this hashtable,
 469      *          or <code>null</code> if the key did not have a mapping
 470      * @throws  NullPointerException  if the key is <code>null</code>
 471      */
 472     public synchronized V remove(Object key) {
 473         Entry tab[] = table;
 474         int hash = key.hashCode();
 475         int index = (hash & 0x7FFFFFFF) % tab.length;
 476         for (Entry<K,V> e = tab[index], prev = null ; e != null ; prev = e, e = e.next) {
 477             if ((e.hash == hash) && e.key.equals(key)) {
 478                 modCount++;
 479                 if (prev != null) {
 480                     prev.next = e.next;
 481                 } else {
 482                     tab[index] = e.next;
 483                 }
 484                 count--;
 485                 V oldValue = e.value;
 486                 e.value = null;
 487                 return oldValue;
 488             }
 489         }
 490         return null;
 491     }
 492 
 493     /**
 494      * Copies all of the mappings from the specified map to this hashtable.


 661         if (entrySet==null)
 662             entrySet = Collections.synchronizedSet(new EntrySet(), this);
 663         return entrySet;
 664     }
 665 
 666     private class EntrySet extends AbstractSet<Map.Entry<K,V>> {
 667         public Iterator<Map.Entry<K,V>> iterator() {
 668             return getIterator(ENTRIES);
 669         }
 670 
 671         public boolean add(Map.Entry<K,V> o) {
 672             return super.add(o);
 673         }
 674 
 675         public boolean contains(Object o) {
 676             if (!(o instanceof Map.Entry))
 677                 return false;
 678             Map.Entry entry = (Map.Entry)o;
 679             Object key = entry.getKey();
 680             Entry[] tab = table;
 681             int hash = key.hashCode();
 682             int index = (hash & 0x7FFFFFFF) % tab.length;
 683 
 684             for (Entry e = tab[index]; e != null; e = e.next)
 685                 if (e.hash==hash && e.equals(entry))
 686                     return true;
 687             return false;
 688         }
 689 
 690         public boolean remove(Object o) {
 691             if (!(o instanceof Map.Entry))
 692                 return false;
 693             Map.Entry<K,V> entry = (Map.Entry<K,V>) o;
 694             K key = entry.getKey();
 695             Entry[] tab = table;
 696             int hash = key.hashCode();
 697             int index = (hash & 0x7FFFFFFF) % tab.length;
 698 
 699             for (Entry<K,V> e = tab[index], prev = null; e != null;
 700                  prev = e, e = e.next) {
 701                 if (e.hash==hash && e.equals(entry)) {
 702                     modCount++;
 703                     if (prev != null)
 704                         prev.next = e.next;
 705                     else
 706                         tab[index] = e.next;
 707 
 708                     count--;
 709                     e.value = null;
 710                     return true;
 711                 }
 712             }
 713             return false;
 714         }
 715 
 716         public int size() {


 810      * @see Map#hashCode()
 811      * @since 1.2
 812      */
 813     public synchronized int hashCode() {
 814         /*
 815          * This code detects the recursion caused by computing the hash code
 816          * of a self-referential hash table and prevents the stack overflow
 817          * that would otherwise result.  This allows certain 1.1-era
 818          * applets with self-referential hash tables to work.  This code
 819          * abuses the loadFactor field to do double-duty as a hashCode
 820          * in progress flag, so as not to worsen the space performance.
 821          * A negative load factor indicates that hash code computation is
 822          * in progress.
 823          */
 824         int h = 0;
 825         if (count == 0 || loadFactor < 0)
 826             return h;  // Returns zero
 827 
 828         loadFactor = -loadFactor;  // Mark hashCode computation in progress
 829         Entry[] tab = table;
 830         for (int i = 0; i < tab.length; i++)
 831             for (Entry e = tab[i]; e != null; e = e.next)
 832                 h += e.key.hashCode() ^ e.value.hashCode();


 833         loadFactor = -loadFactor;  // Mark hashCode computation complete
 834 
 835         return h;
 836     }
 837 
 838     /**
 839      * Save the state of the Hashtable to a stream (i.e., serialize it).
 840      *
 841      * @serialData The <i>capacity</i> of the Hashtable (the length of the
 842      *             bucket array) is emitted (int), followed by the
 843      *             <i>size</i> of the Hashtable (the number of key-value
 844      *             mappings), followed by the key (Object) and value (Object)
 845      *             for each key-value mapping represented by the Hashtable
 846      *             The key-value mappings are emitted in no particular order.
 847      */
 848     private void writeObject(java.io.ObjectOutputStream s)
 849             throws IOException {
 850         Entry<Object, Object> entryStack = null;
 851 
 852         synchronized (this) {
 853             // Write out the length, threshold, loadfactor
 854             s.defaultWriteObject();
 855 
 856             // Write out length, count of elements
 857             s.writeInt(table.length);
 858             s.writeInt(count);
 859 
 860             // Stack copies of the entries in the table
 861             for (int index = 0; index < table.length; index++) {
 862                 Entry entry = table[index];
 863 
 864                 while (entry != null) {
 865                     entryStack =
 866                         new Entry<>(0, entry.key, entry.value, entryStack);
 867                     entry = entry.next;
 868                 }
 869             }
 870         }
 871 
 872         // Write out the key/value objects from the stacked entries
 873         while (entryStack != null) {
 874             s.writeObject(entryStack.key);
 875             s.writeObject(entryStack.value);
 876             entryStack = entryStack.next;
 877         }
 878     }
 879 
 880     /**
 881      * Reconstitute the Hashtable from a stream (i.e., deserialize it).
 882      */
 883     private void readObject(java.io.ObjectInputStream s)
 884          throws IOException, ClassNotFoundException
 885     {
 886         // Read in the length, threshold, and loadfactor
 887         s.defaultReadObject();
 888 




 889         // Read the original length of the array and number of elements
 890         int origlength = s.readInt();
 891         int elements = s.readInt();
 892 
 893         // Compute new size with a bit of room 5% to grow but
 894         // no larger than the original size.  Make the length
 895         // odd if it's large enough, this helps distribute the entries.
 896         // Guard against the length ending up zero, that's not valid.
 897         int length = (int)(elements * loadFactor) + (elements / 20) + 3;
 898         if (length > elements && (length & 1) == 0)
 899             length--;
 900         if (origlength > 0 && length > origlength)
 901             length = origlength;
 902 
 903         Entry[] table = new Entry[length];

 904         count = 0;


 905 
 906         // Read the number of elements and then all the key/value objects
 907         for (; elements > 0; elements--) {
 908             K key = (K)s.readObject();
 909             V value = (V)s.readObject();
 910             // synch could be eliminated for performance
 911             reconstitutionPut(table, key, value);
 912         }
 913         this.table = table;
 914     }
 915 
 916     /**
 917      * The put method used by readObject. This is provided because put
 918      * is overridable and should not be called in readObject since the
 919      * subclass will not yet be initialized.
 920      *
 921      * <p>This differs from the regular put method in several ways. No
 922      * checking for rehashing is necessary since the number of elements
 923      * initially in the table is known. The modCount is not incremented
 924      * because we are creating a new instance. Also, no return value
 925      * is needed.
 926      */
 927     private void reconstitutionPut(Entry[] tab, K key, V value)
 928         throws StreamCorruptedException
 929     {
 930         if (value == null) {
 931             throw new java.io.StreamCorruptedException();
 932         }
 933         // Makes sure the key is not already in the hashtable.
 934         // This should not happen in deserialized version.
 935         int hash = key.hashCode();
 936         int index = (hash & 0x7FFFFFFF) % tab.length;
 937         for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {
 938             if ((e.hash == hash) && e.key.equals(key)) {
 939                 throw new java.io.StreamCorruptedException();
 940             }
 941         }
 942         // Creates the new entry.
 943         Entry<K,V> e = tab[index];
 944         tab[index] = new Entry<>(hash, key, value, e);
 945         count++;
 946     }
 947 
 948     /**
 949      * Hashtable collision list.
 950      */
 951     private static class Entry<K,V> implements Map.Entry<K,V> {
 952         int hash;
 953         K key;
 954         V value;
 955         Entry<K,V> next;
 956 
 957         protected Entry(int hash, K key, V value, Entry<K,V> next) {
 958             this.hash = hash;
 959             this.key = key;
 960             this.value = value;
 961             this.next = next;
 962         }
 963 
 964         protected Object clone() {
 965             return new Entry<>(hash, key, value,
 966                                   (next==null ? null : (Entry<K,V>) next.clone()));
 967         }
 968 
 969         // Map.Entry Ops


 971         public K getKey() {
 972             return key;
 973         }
 974 
 975         public V getValue() {
 976             return value;
 977         }
 978 
 979         public V setValue(V value) {
 980             if (value == null)
 981                 throw new NullPointerException();
 982 
 983             V oldValue = this.value;
 984             this.value = value;
 985             return oldValue;
 986         }
 987 
 988         public boolean equals(Object o) {
 989             if (!(o instanceof Map.Entry))
 990                 return false;
 991             Map.Entry e = (Map.Entry)o;
 992 
 993             return (key==null ? e.getKey()==null : key.equals(e.getKey())) &&
 994                (value==null ? e.getValue()==null : value.equals(e.getValue()));
 995         }
 996 
 997         public int hashCode() {
 998             return hash ^ (value==null ? 0 : value.hashCode());
 999         }
1000 
1001         public String toString() {
1002             return key.toString()+"="+value.toString();
1003         }
1004     }
1005 
1006     // Types of Enumerations/Iterations
1007     private static final int KEYS = 0;
1008     private static final int VALUES = 1;
1009     private static final int ENTRIES = 2;
1010 
1011     /**
1012      * A hashtable enumerator class.  This class implements both the
1013      * Enumeration and Iterator interfaces, but individual instances
1014      * can be created with the Iterator methods disabled.  This is necessary
1015      * to avoid unintentionally increasing the capabilities granted a user
1016      * by passing an Enumeration.
1017      */
1018     private class Enumerator<T> implements Enumeration<T>, Iterator<T> {




 112  *
 113  * @author  Arthur van Hoff
 114  * @author  Josh Bloch
 115  * @author  Neal Gafter
 116  * @see     Object#equals(java.lang.Object)
 117  * @see     Object#hashCode()
 118  * @see     Hashtable#rehash()
 119  * @see     Collection
 120  * @see     Map
 121  * @see     HashMap
 122  * @see     TreeMap
 123  * @since JDK1.0
 124  */
 125 public class Hashtable<K,V>
 126     extends Dictionary<K,V>
 127     implements Map<K,V>, Cloneable, java.io.Serializable {
 128 
 129     /**
 130      * The hash table data.
 131      */
 132     private transient Entry<K,V>[] table;
 133 
 134     /**
 135      * The total number of entries in the hash table.
 136      */
 137     private transient int count;
 138 
 139     /**
 140      * The table is rehashed when its size exceeds this threshold.  (The
 141      * value of this field is (int)(capacity * loadFactor).)
 142      *
 143      * @serial
 144      */
 145     private int threshold;
 146 
 147     /**
 148      * The load factor for the hashtable.
 149      *
 150      * @serial
 151      */
 152     private float loadFactor;
 153 
 154     /**
 155      * The number of times this Hashtable has been structurally modified
 156      * Structural modifications are those that change the number of entries in
 157      * the Hashtable or otherwise modify its internal structure (e.g.,
 158      * rehash).  This field is used to make iterators on Collection-views of
 159      * the Hashtable fail-fast.  (See ConcurrentModificationException).
 160      */
 161     private transient int modCount = 0;
 162 
 163     /** use serialVersionUID from JDK 1.0.2 for interoperability */
 164     private static final long serialVersionUID = 1421746759512286392L;
 165     
 166     /**
 167      * The default threshold of capacity above which alternate hashing is used. 
 168      * Alternative hashing reduces the incidence of collisions due to weak hash
 169      * code calculation. 
 170      * <p/>
 171      * This value may be overridden by defining the system property 
 172      * {@code java.util.althashing.threshold}. A property value of {@code 1}
 173      * forces alternative hashing to be used at all times whereas
 174      * {@code 2147483648 } ({@code Integer.MAX_VALUE}) value ensures that
 175      * alternative hashing is never used.
 176      */
 177     static final int ALTERNATE_HASHING_THRESHOLD_DEFAULT = 0;
 178     
 179     /**
 180      * holds values which can't be initialized until after VM is booted.
 181      */
 182     private static class Holder {
 183 
 184         /**
 185          * Table capacity above which to switch to use alternate hashing.
 186          */
 187         static final int ALTERNATE_HASHING_THRESHOLD;
 188         
 189         static {
 190             String altThreshold = java.security.AccessController.doPrivileged(
 191                 new sun.security.action.GetPropertyAction(
 192                     "jdk.map.althashing.threshold"));
 193             
 194             int threshold;
 195             try {
 196                 threshold = (null != altThreshold)
 197                         ? Integer.parseInt(altThreshold)
 198                         : 1;
 199                 
 200                 if(threshold == -1) {
 201                     threshold = Integer.MAX_VALUE;
 202                 }
 203 
 204                 if(threshold < 0) {
 205                     throw new IllegalArgumentException("value must be positive integer.");
 206                 }
 207             } catch(IllegalArgumentException failed) {
 208                 throw new Error("Illegal value for 'jdk.map.althashing.threshold'", failed);
 209             }
 210             
 211             ALTERNATE_HASHING_THRESHOLD = threshold;
 212         }
 213     }
 214             
 215     /** 
 216      * If {@code true} then perform alternate hashing to reduce the incidence of
 217      * collisions due to weak hash code calculation.
 218      */
 219     transient boolean useAltHashing;
 220     
 221     // Unsafe mechanics
 222     private static final sun.misc.Unsafe UNSAFE;
 223     private static final long HASHSEED_OFFSET;
 224     
 225      static {
 226         try {
 227             UNSAFE = sun.misc.Unsafe.getUnsafe();
 228             HASHSEED_OFFSET = UNSAFE.objectFieldOffset(
 229                 Hashtable.class.getDeclaredField("hashSeed"));                        
 230         } catch (NoSuchFieldException | SecurityException e) {
 231             throw new Error("Failed to record hashSeed offset", e);
 232         }
 233      }
 234      
 235     /**
 236      * A randomizing value associated with this instance that is applied to  
 237      * hash code of keys to make hash collisions harder to find.
 238      */
 239     transient final int hashSeed = sun.misc.Hashing.randomHashSeed(this);
 240 
 241     private int hash(Object k) {
 242         if (useAltHashing) {
 243             int h = hashSeed;
 244             if (k.getClass() == String.class) {
 245                 return h ^ sun.misc.Hashing.stringHash32((String) k);
 246             } else {
 247                 h ^= k.hashCode();
 248  
 249                 // This function ensures that hashCodes that differ only by
 250                 // constant multiples at each bit position have a bounded
 251                 // number of collisions (approximately 8 at default load factor).
 252                 h ^= (h >>> 20) ^ (h >>> 12);
 253                 return h ^ (h >>> 7) ^ (h >>> 4);
 254              }
 255         } else  {
 256             return k.hashCode();
 257         }
 258     }
 259 
 260     /**
 261      * Constructs a new, empty hashtable with the specified initial
 262      * capacity and the specified load factor.
 263      *
 264      * @param      initialCapacity   the initial capacity of the hashtable.
 265      * @param      loadFactor        the load factor of the hashtable.
 266      * @exception  IllegalArgumentException  if the initial capacity is less
 267      *             than zero, or if the load factor is nonpositive.
 268      */
 269     public Hashtable(int initialCapacity, float loadFactor) {
 270         if (initialCapacity < 0)
 271             throw new IllegalArgumentException("Illegal Capacity: "+
 272                                                initialCapacity);
 273         if (loadFactor <= 0 || Float.isNaN(loadFactor))
 274             throw new IllegalArgumentException("Illegal Load: "+loadFactor);
 275 
 276         if (initialCapacity==0)
 277             initialCapacity = 1;
 278         this.loadFactor = loadFactor;
 279         table = new Entry[initialCapacity];
 280         threshold = (int)Math.min(initialCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
 281         useAltHashing = sun.misc.VM.isBooted() &&
 282                 (initialCapacity >= Holder.ALTERNATE_HASHING_THRESHOLD);
 283     }
 284 
 285     /**
 286      * Constructs a new, empty hashtable with the specified initial capacity
 287      * and default load factor (0.75).
 288      *
 289      * @param     initialCapacity   the initial capacity of the hashtable.
 290      * @exception IllegalArgumentException if the initial capacity is less
 291      *              than zero.
 292      */
 293     public Hashtable(int initialCapacity) {
 294         this(initialCapacity, 0.75f);
 295     }
 296 
 297     /**
 298      * Constructs a new, empty hashtable with a default initial capacity (11)
 299      * and load factor (0.75).
 300      */
 301     public Hashtable() {
 302         this(11, 0.75f);


 406      *         specified value
 407      * @throws NullPointerException  if the value is <code>null</code>
 408      * @since 1.2
 409      */
 410     public boolean containsValue(Object value) {
 411         return contains(value);
 412     }
 413 
 414     /**
 415      * Tests if the specified object is a key in this hashtable.
 416      *
 417      * @param   key   possible key
 418      * @return  <code>true</code> if and only if the specified object
 419      *          is a key in this hashtable, as determined by the
 420      *          <tt>equals</tt> method; <code>false</code> otherwise.
 421      * @throws  NullPointerException  if the key is <code>null</code>
 422      * @see     #contains(Object)
 423      */
 424     public synchronized boolean containsKey(Object key) {
 425         Entry tab[] = table;
 426         int hash = hash(key);
 427         int index = (hash & 0x7FFFFFFF) % tab.length;
 428         for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {
 429             if ((e.hash == hash) && e.key.equals(key)) {
 430                 return true;
 431             }
 432         }
 433         return false;
 434     }
 435 
 436     /**
 437      * Returns the value to which the specified key is mapped,
 438      * or {@code null} if this map contains no mapping for the key.
 439      *
 440      * <p>More formally, if this map contains a mapping from a key
 441      * {@code k} to a value {@code v} such that {@code (key.equals(k))},
 442      * then this method returns {@code v}; otherwise it returns
 443      * {@code null}.  (There can be at most one such mapping.)
 444      *
 445      * @param key the key whose associated value is to be returned
 446      * @return the value to which the specified key is mapped, or
 447      *         {@code null} if this map contains no mapping for the key
 448      * @throws NullPointerException if the specified key is null
 449      * @see     #put(Object, Object)
 450      */
 451     public synchronized V get(Object key) {
 452         Entry tab[] = table;
 453         int hash = hash(key);
 454         int index = (hash & 0x7FFFFFFF) % tab.length;
 455         for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {
 456             if ((e.hash == hash) && e.key.equals(key)) {
 457                 return e.value;
 458             }
 459         }
 460         return null;
 461     }
 462 
 463     /**
 464      * The maximum size of array to allocate.
 465      * Some VMs reserve some header words in an array.
 466      * Attempts to allocate larger arrays may result in
 467      * OutOfMemoryError: Requested array size exceeds VM limit
 468      */
 469     private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
 470 
 471     /**
 472      * Increases the capacity of and internally reorganizes this
 473      * hashtable, in order to accommodate and access its entries more
 474      * efficiently.  This method is called automatically when the
 475      * number of keys in the hashtable exceeds this hashtable's capacity
 476      * and load factor.
 477      */
 478     protected void rehash() {
 479         int oldCapacity = table.length;
 480         Entry<K,V>[] oldMap = table;
 481 
 482         // overflow-conscious code
 483         int newCapacity = (oldCapacity << 1) + 1;
 484         if (newCapacity - MAX_ARRAY_SIZE > 0) {
 485             if (oldCapacity == MAX_ARRAY_SIZE)
 486                 // Keep running with MAX_ARRAY_SIZE buckets
 487                 return;
 488             newCapacity = MAX_ARRAY_SIZE;
 489         }
 490         Entry<K,V>[] newMap = new Entry[newCapacity];
 491 
 492         modCount++;
 493         threshold = (int)Math.min(newCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
 494         boolean currentAltHashing = useAltHashing;
 495         useAltHashing = sun.misc.VM.isBooted() && 
 496                 (newCapacity >= Holder.ALTERNATE_HASHING_THRESHOLD);
 497         boolean rehash = currentAltHashing ^ useAltHashing;
 498         
 499         table = newMap;
 500 
 501         for (int i = oldCapacity ; i-- > 0 ;) {
 502             for (Entry<K,V> old = oldMap[i] ; old != null ; ) {
 503                 Entry<K,V> e = old;
 504                 old = old.next;
 505 
 506                 if(rehash) {
 507                     e.hash = hash(e.key);
 508                 }
 509                 int index = (e.hash & 0x7FFFFFFF) % newCapacity;
 510                 e.next = newMap[index];
 511                 newMap[index] = e;
 512             }
 513         }
 514     }
 515 
 516     /**
 517      * Maps the specified <code>key</code> to the specified
 518      * <code>value</code> in this hashtable. Neither the key nor the
 519      * value can be <code>null</code>. <p>
 520      *
 521      * The value can be retrieved by calling the <code>get</code> method
 522      * with a key that is equal to the original key.
 523      *
 524      * @param      key     the hashtable key
 525      * @param      value   the value
 526      * @return     the previous value of the specified key in this hashtable,
 527      *             or <code>null</code> if it did not have one
 528      * @exception  NullPointerException  if the key or value is
 529      *               <code>null</code>
 530      * @see     Object#equals(Object)
 531      * @see     #get(Object)
 532      */
 533     public synchronized V put(K key, V value) {
 534         // Make sure the value is not null
 535         if (value == null) {
 536             throw new NullPointerException();
 537         }
 538 
 539         // Makes sure the key is not already in the hashtable.
 540         Entry tab[] = table;
 541         int hash = hash(key);
 542         int index = (hash & 0x7FFFFFFF) % tab.length;
 543         for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {
 544             if ((e.hash == hash) && e.key.equals(key)) {
 545                 V old = e.value;
 546                 e.value = value;
 547                 return old;
 548             }
 549         }
 550 
 551         modCount++;
 552         if (count >= threshold) {
 553             // Rehash the table if the threshold is exceeded
 554             rehash();
 555 
 556             tab = table;
 557             hash = hash(key);
 558             index = (hash & 0x7FFFFFFF) % tab.length;
 559         }
 560 
 561         // Creates the new entry.
 562         Entry<K,V> e = tab[index];
 563         tab[index] = new Entry<>(hash, key, value, e);
 564         count++;
 565         return null;
 566     }
 567 
 568     /**
 569      * Removes the key (and its corresponding value) from this
 570      * hashtable. This method does nothing if the key is not in the hashtable.
 571      *
 572      * @param   key   the key that needs to be removed
 573      * @return  the value to which the key had been mapped in this hashtable,
 574      *          or <code>null</code> if the key did not have a mapping
 575      * @throws  NullPointerException  if the key is <code>null</code>
 576      */
 577     public synchronized V remove(Object key) {
 578         Entry tab[] = table;
 579         int hash = hash(key);
 580         int index = (hash & 0x7FFFFFFF) % tab.length;
 581         for (Entry<K,V> e = tab[index], prev = null ; e != null ; prev = e, e = e.next) {
 582             if ((e.hash == hash) && e.key.equals(key)) {
 583                 modCount++;
 584                 if (prev != null) {
 585                     prev.next = e.next;
 586                 } else {
 587                     tab[index] = e.next;
 588                 }
 589                 count--;
 590                 V oldValue = e.value;
 591                 e.value = null;
 592                 return oldValue;
 593             }
 594         }
 595         return null;
 596     }
 597 
 598     /**
 599      * Copies all of the mappings from the specified map to this hashtable.


 766         if (entrySet==null)
 767             entrySet = Collections.synchronizedSet(new EntrySet(), this);
 768         return entrySet;
 769     }
 770 
 771     private class EntrySet extends AbstractSet<Map.Entry<K,V>> {
 772         public Iterator<Map.Entry<K,V>> iterator() {
 773             return getIterator(ENTRIES);
 774         }
 775 
 776         public boolean add(Map.Entry<K,V> o) {
 777             return super.add(o);
 778         }
 779 
 780         public boolean contains(Object o) {
 781             if (!(o instanceof Map.Entry))
 782                 return false;
 783             Map.Entry entry = (Map.Entry)o;
 784             Object key = entry.getKey();
 785             Entry[] tab = table;
 786             int hash = hash(key);
 787             int index = (hash & 0x7FFFFFFF) % tab.length;
 788 
 789             for (Entry e = tab[index]; e != null; e = e.next)
 790                 if (e.hash==hash && e.equals(entry))
 791                     return true;
 792             return false;
 793         }
 794 
 795         public boolean remove(Object o) {
 796             if (!(o instanceof Map.Entry))
 797                 return false;
 798             Map.Entry<K,V> entry = (Map.Entry<K,V>) o;
 799             K key = entry.getKey();
 800             Entry[] tab = table;
 801             int hash = hash(key);
 802             int index = (hash & 0x7FFFFFFF) % tab.length;
 803 
 804             for (Entry<K,V> e = tab[index], prev = null; e != null;
 805                  prev = e, e = e.next) {
 806                 if (e.hash==hash && e.equals(entry)) {
 807                     modCount++;
 808                     if (prev != null)
 809                         prev.next = e.next;
 810                     else
 811                         tab[index] = e.next;
 812 
 813                     count--;
 814                     e.value = null;
 815                     return true;
 816                 }
 817             }
 818             return false;
 819         }
 820 
 821         public int size() {


 915      * @see Map#hashCode()
 916      * @since 1.2
 917      */
 918     public synchronized int hashCode() {
 919         /*
 920          * This code detects the recursion caused by computing the hash code
 921          * of a self-referential hash table and prevents the stack overflow
 922          * that would otherwise result.  This allows certain 1.1-era
 923          * applets with self-referential hash tables to work.  This code
 924          * abuses the loadFactor field to do double-duty as a hashCode
 925          * in progress flag, so as not to worsen the space performance.
 926          * A negative load factor indicates that hash code computation is
 927          * in progress.
 928          */
 929         int h = 0;
 930         if (count == 0 || loadFactor < 0)
 931             return h;  // Returns zero
 932 
 933         loadFactor = -loadFactor;  // Mark hashCode computation in progress
 934         Entry[] tab = table;
 935         for (Entry<K,V> entry : tab)
 936             while (entry != null) {
 937                 h += entry.hashCode();
 938                 entry = entry.next;
 939             }
 940         loadFactor = -loadFactor;  // Mark hashCode computation complete
 941 
 942         return h;
 943     }
 944 
 945     /**
 946      * Save the state of the Hashtable to a stream (i.e., serialize it).
 947      *
 948      * @serialData The <i>capacity</i> of the Hashtable (the length of the
 949      *             bucket array) is emitted (int), followed by the
 950      *             <i>size</i> of the Hashtable (the number of key-value
 951      *             mappings), followed by the key (Object) and value (Object)
 952      *             for each key-value mapping represented by the Hashtable
 953      *             The key-value mappings are emitted in no particular order.
 954      */
 955     private void writeObject(java.io.ObjectOutputStream s)
 956             throws IOException {
 957         Entry<K, V> entryStack = null;
 958 
 959         synchronized (this) {
 960             // Write out the length, threshold, loadfactor
 961             s.defaultWriteObject();
 962 
 963             // Write out length, count of elements
 964             s.writeInt(table.length);
 965             s.writeInt(count);
 966 
 967             // Stack copies of the entries in the table
 968             for (int index = 0; index < table.length; index++) {
 969                 Entry<K,V> entry = table[index];
 970 
 971                 while (entry != null) {
 972                     entryStack =
 973                         new Entry<>(0, entry.key, entry.value, entryStack);
 974                     entry = entry.next;
 975                 }
 976             }
 977         }
 978 
 979         // Write out the key/value objects from the stacked entries
 980         while (entryStack != null) {
 981             s.writeObject(entryStack.key);
 982             s.writeObject(entryStack.value);
 983             entryStack = entryStack.next;
 984         }
 985     }
 986 
 987     /**
 988      * Reconstitute the Hashtable from a stream (i.e., deserialize it).
 989      */
 990     private void readObject(java.io.ObjectInputStream s)
 991          throws IOException, ClassNotFoundException
 992     {
 993         // Read in the length, threshold, and loadfactor
 994         s.defaultReadObject();
 995         
 996         // set hashSeed
 997         UNSAFE.putIntVolatile(this, HASHSEED_OFFSET, 
 998                 sun.misc.Hashing.randomHashSeed(this));        
 999 
1000         // Read the original length of the array and number of elements
1001         int origlength = s.readInt();
1002         int elements = s.readInt();
1003 
1004         // Compute new size with a bit of room 5% to grow but
1005         // no larger than the original size.  Make the length
1006         // odd if it's large enough, this helps distribute the entries.
1007         // Guard against the length ending up zero, that's not valid.
1008         int length = (int)(elements * loadFactor) + (elements / 20) + 3;
1009         if (length > elements && (length & 1) == 0)
1010             length--;
1011         if (origlength > 0 && length > origlength)
1012             length = origlength;
1013 
1014         Entry<K,V>[] table = new Entry[length];
1015         threshold = (int) Math.min(length * loadFactor, MAX_ARRAY_SIZE + 1);
1016         count = 0;
1017         useAltHashing = sun.misc.VM.isBooted() && 
1018                 (length >= Holder.ALTERNATE_HASHING_THRESHOLD);
1019 
1020         // Read the number of elements and then all the key/value objects
1021         for (; elements > 0; elements--) {
1022             K key = (K)s.readObject();
1023             V value = (V)s.readObject();
1024             // synch could be eliminated for performance
1025             reconstitutionPut(table, key, value);
1026         }
1027         this.table = table;
1028     }
1029 
1030     /**
1031      * The put method used by readObject. This is provided because put
1032      * is overridable and should not be called in readObject since the
1033      * subclass will not yet be initialized.
1034      *
1035      * <p>This differs from the regular put method in several ways. No
1036      * checking for rehashing is necessary since the number of elements
1037      * initially in the table is known. The modCount is not incremented
1038      * because we are creating a new instance. Also, no return value
1039      * is needed.
1040      */
1041     private void reconstitutionPut(Entry<K,V>[] tab, K key, V value)
1042         throws StreamCorruptedException
1043     {
1044         if (value == null) {
1045             throw new java.io.StreamCorruptedException();
1046         }
1047         // Makes sure the key is not already in the hashtable.
1048         // This should not happen in deserialized version.
1049         int hash = hash(key);
1050         int index = (hash & 0x7FFFFFFF) % tab.length;
1051         for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {
1052             if ((e.hash == hash) && e.key.equals(key)) {
1053                 throw new java.io.StreamCorruptedException();
1054             }
1055         }
1056         // Creates the new entry.
1057         Entry<K,V> e = tab[index];
1058         tab[index] = new Entry<>(hash, key, value, e);
1059         count++;
1060     }
1061 
1062     /**
1063      * Hashtable bucket collision list entry
1064      */
1065     private static class Entry<K,V> implements Map.Entry<K,V> {
1066         int hash;
1067         K key;
1068         V value;
1069         Entry<K,V> next;
1070 
1071         protected Entry(int hash, K key, V value, Entry<K,V> next) {
1072             this.hash = hash;
1073             this.key =  key;
1074             this.value = value;
1075             this.next = next;
1076         }
1077 
1078         protected Object clone() {
1079             return new Entry<>(hash, key, value,
1080                                   (next==null ? null : (Entry<K,V>) next.clone()));
1081         }
1082 
1083         // Map.Entry Ops


1085         public K getKey() {
1086             return key;
1087         }
1088 
1089         public V getValue() {
1090             return value;
1091         }
1092 
1093         public V setValue(V value) {
1094             if (value == null)
1095                 throw new NullPointerException();
1096 
1097             V oldValue = this.value;
1098             this.value = value;
1099             return oldValue;
1100         }
1101 
1102         public boolean equals(Object o) {
1103             if (!(o instanceof Map.Entry))
1104                 return false;
1105             Map.Entry<?,?> e = (Map.Entry)o;
1106 
1107             return key.equals(e.getKey()) && value.equals(e.getValue());

1108         }
1109 
1110         public int hashCode() {
1111             return hash ^ value.hashCode();
1112         }
1113 
1114         public String toString() {
1115             return key.toString()+"="+value.toString();
1116         }
1117     }
1118 
1119     // Types of Enumerations/Iterations
1120     private static final int KEYS = 0;
1121     private static final int VALUES = 1;
1122     private static final int ENTRIES = 2;
1123 
1124     /**
1125      * A hashtable enumerator class.  This class implements both the
1126      * Enumeration and Iterator interfaces, but individual instances
1127      * can be created with the Iterator methods disabled.  This is necessary
1128      * to avoid unintentionally increasing the capabilities granted a user
1129      * by passing an Enumeration.
1130      */
1131     private class Enumerator<T> implements Enumeration<T>, Iterator<T> {