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

Print this page
rev 5380 : 7126277: Alternative hashing implementation


 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<?,?> 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     @SuppressWarnings("unchecked")
 356     public synchronized V get(Object key) {
 357         Entry<?,?> tab[] = table;
 358         int hash = key.hashCode();
 359         int index = (hash & 0x7FFFFFFF) % tab.length;
 360         for (Entry<?,?> e = tab[index] ; e != null ; e = e.next) {
 361             if ((e.hash == hash) && e.key.equals(key)) {
 362                 return (V)e.value;
 363             }
 364         }
 365         return null;
 366     }
 367 
 368     /**
 369      * The maximum size of array to allocate.
 370      * Some VMs reserve some header words in an array.
 371      * Attempts to allocate larger arrays may result in
 372      * OutOfMemoryError: Requested array size exceeds VM limit
 373      */
 374     private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
 375 
 376     /**
 377      * Increases the capacity of and internally reorganizes this
 378      * hashtable, in order to accommodate and access its entries more
 379      * efficiently.  This method is called automatically when the
 380      * number of keys in the hashtable exceeds this hashtable's capacity
 381      * and load factor.
 382      */
 383     @SuppressWarnings("unchecked")
 384     protected void rehash() {
 385         int oldCapacity = table.length;
 386         Entry<?,?>[] oldMap = table;
 387 
 388         // overflow-conscious code
 389         int newCapacity = (oldCapacity << 1) + 1;
 390         if (newCapacity - MAX_ARRAY_SIZE > 0) {
 391             if (oldCapacity == MAX_ARRAY_SIZE)
 392                 // Keep running with MAX_ARRAY_SIZE buckets
 393                 return;
 394             newCapacity = MAX_ARRAY_SIZE;
 395         }
 396         Entry<?,?>[] newMap = new Entry<?,?>[newCapacity];
 397 
 398         modCount++;
 399         threshold = (int)(newCapacity * loadFactor);
 400         table = newMap;
 401 
 402         for (int i = oldCapacity ; i-- > 0 ;) {
 403             for (Entry<K,V> old = (Entry<K,V>)oldMap[i] ; old != null ; ) {
 404                 Entry<K,V> e = old;
 405                 old = old.next;
 406 
 407                 int index = (e.hash & 0x7FFFFFFF) % newCapacity;
 408                 e.next = (Entry<K,V>)newMap[index];
 409                 newMap[index] = e;
 410             }
 411         }
 412     }
 413 
 414     /**
 415      * Maps the specified <code>key</code> to the specified
 416      * <code>value</code> in this hashtable. Neither the key nor the
 417      * value can be <code>null</code>. <p>
 418      *
 419      * The value can be retrieved by calling the <code>get</code> method
 420      * with a key that is equal to the original key.
 421      *
 422      * @param      key     the hashtable key
 423      * @param      value   the value
 424      * @return     the previous value of the specified key in this hashtable,
 425      *             or <code>null</code> if it did not have one
 426      * @exception  NullPointerException  if the key or value is
 427      *               <code>null</code>
 428      * @see     Object#equals(Object)
 429      * @see     #get(Object)
 430      */
 431     public synchronized V put(K key, V value) {
 432         // Make sure the value is not null
 433         if (value == null) {
 434             throw new NullPointerException();
 435         }
 436 
 437         // Makes sure the key is not already in the hashtable.
 438         Entry<?,?> tab[] = table;
 439         int hash = key.hashCode();
 440         int index = (hash & 0x7FFFFFFF) % tab.length;
 441         @SuppressWarnings("unchecked")
 442         Entry<K,V> entry = (Entry<K,V>)tab[index];
 443         for(; entry != null ; entry = entry.next) {
 444             if ((entry.hash == hash) && entry.key.equals(key)) {
 445                 V old = entry.value;
 446                 entry.value = value;
 447                 return old;
 448             }
 449         }
 450 
 451         modCount++;
 452         if (count >= threshold) {
 453             // Rehash the table if the threshold is exceeded
 454             rehash();
 455 
 456             tab = table;

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


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


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




 841         loadFactor = -loadFactor;  // Mark hashCode computation complete
 842 
 843         return h;
 844     }
 845 
 846     /**
 847      * Save the state of the Hashtable to a stream (i.e., serialize it).
 848      *
 849      * @serialData The <i>capacity</i> of the Hashtable (the length of the
 850      *             bucket array) is emitted (int), followed by the
 851      *             <i>size</i> of the Hashtable (the number of key-value
 852      *             mappings), followed by the key (Object) and value (Object)
 853      *             for each key-value mapping represented by the Hashtable
 854      *             The key-value mappings are emitted in no particular order.
 855      */
 856     private void writeObject(java.io.ObjectOutputStream s)
 857             throws IOException {
 858         Entry<Object, Object> entryStack = null;
 859 
 860         synchronized (this) {


 877             }
 878         }
 879 
 880         // Write out the key/value objects from the stacked entries
 881         while (entryStack != null) {
 882             s.writeObject(entryStack.key);
 883             s.writeObject(entryStack.value);
 884             entryStack = entryStack.next;
 885         }
 886     }
 887 
 888     /**
 889      * Reconstitute the Hashtable from a stream (i.e., deserialize it).
 890      */
 891     private void readObject(java.io.ObjectInputStream s)
 892          throws IOException, ClassNotFoundException
 893     {
 894         // Read in the length, threshold, and loadfactor
 895         s.defaultReadObject();
 896 




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

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




 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     private static class Holder {
 167             // Unsafe mechanics
 168         /**
 169          * 
 170          */
 171         private static final sun.misc.Unsafe UNSAFE;
 172         
 173         /**
 174          * Offset of "final" hashmask field we must set in
 175          * readObject() method.
 176          */
 177         private static final long HASHMASK_OFFSET;
 178                 
 179         static {           
 180             try {
 181                 UNSAFE = sun.misc.Unsafe.getUnsafe();
 182                 HASHMASK_OFFSET = UNSAFE.objectFieldOffset(
 183                     Hashtable.class.getDeclaredField("hashMask"));                        
 184             } catch (NoSuchFieldException | SecurityException e) {
 185                 throw new InternalError("Failed to record hashMask offset", e);
 186             }
 187         }
 188     }
 189     
 190     /**
 191      * A random mask value that is used for hashcode values associated with this
 192      * instance to make hash collisions harder to find.
 193      */
 194     transient final int hashMask = sun.misc.Hashing.makeHashMask(this);
 195 
 196     private int hash(Object k) {
 197         int h = hashMask;
 198         if (0 != h) {
 199             if (k instanceof String) {
 200                 h ^= ((String)k).hash32();
 201             } else {
 202                 h ^= k.hashCode();
 203  
 204                 // This function ensures that hashCodes that differ only by
 205                 // constant multiples at each bit position have a bounded
 206                 // number of collisions (approximately 8 at default load factor).
 207                 h ^= (h >>> 20) ^ (h >>> 12);
 208                 h ^= (h >>> 7) ^ (h >>> 4);
 209              }
 210         } else  {
 211             h = k.hashCode();
 212         }
 213         
 214         return h;
 215     }
 216 
 217     /**
 218      * Constructs a new, empty hashtable with the specified initial
 219      * capacity and the specified load factor.
 220      *
 221      * @param      initialCapacity   the initial capacity of the hashtable.
 222      * @param      loadFactor        the load factor of the hashtable.
 223      * @exception  IllegalArgumentException  if the initial capacity is less
 224      *             than zero, or if the load factor is nonpositive.
 225      */
 226     public Hashtable(int initialCapacity, float loadFactor) {
 227         if (initialCapacity < 0)
 228             throw new IllegalArgumentException("Illegal Capacity: "+
 229                                                initialCapacity);
 230         if (loadFactor <= 0 || Float.isNaN(loadFactor))
 231             throw new IllegalArgumentException("Illegal Load: "+loadFactor);
 232 
 233         if (initialCapacity==0)
 234             initialCapacity = 1;
 235         this.loadFactor = loadFactor;
 236         table = new Entry<?,?>[initialCapacity];
 237         threshold = (int)Math.min(initialCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
 238     }
 239 
 240     /**
 241      * Constructs a new, empty hashtable with the specified initial capacity
 242      * and default load factor (0.75).
 243      *
 244      * @param     initialCapacity   the initial capacity of the hashtable.
 245      * @exception IllegalArgumentException if the initial capacity is less
 246      *              than zero.
 247      */
 248     public Hashtable(int initialCapacity) {
 249         this(initialCapacity, 0.75f);
 250     }
 251 
 252     /**
 253      * Constructs a new, empty hashtable with a default initial capacity (11)
 254      * and load factor (0.75).
 255      */
 256     public Hashtable() {
 257         this(11, 0.75f);


 361      *         specified value
 362      * @throws NullPointerException  if the value is <code>null</code>
 363      * @since 1.2
 364      */
 365     public boolean containsValue(Object value) {
 366         return contains(value);
 367     }
 368 
 369     /**
 370      * Tests if the specified object is a key in this hashtable.
 371      *
 372      * @param   key   possible key
 373      * @return  <code>true</code> if and only if the specified object
 374      *          is a key in this hashtable, as determined by the
 375      *          <tt>equals</tt> method; <code>false</code> otherwise.
 376      * @throws  NullPointerException  if the key is <code>null</code>
 377      * @see     #contains(Object)
 378      */
 379     public synchronized boolean containsKey(Object key) {
 380         Entry<?,?> tab[] = table;
 381         int hash = hash(key);
 382         int index = (hash & 0x7FFFFFFF) % tab.length;
 383         for (Entry<?,?> e = tab[index] ; e != null ; e = e.next) {
 384             if ((e.hash == hash) && e.key.equals(key)) {
 385                 return true;
 386             }
 387         }
 388         return false;
 389     }
 390 
 391     /**
 392      * Returns the value to which the specified key is mapped,
 393      * or {@code null} if this map contains no mapping for the key.
 394      *
 395      * <p>More formally, if this map contains a mapping from a key
 396      * {@code k} to a value {@code v} such that {@code (key.equals(k))},
 397      * then this method returns {@code v}; otherwise it returns
 398      * {@code null}.  (There can be at most one such mapping.)
 399      *
 400      * @param key the key whose associated value is to be returned
 401      * @return the value to which the specified key is mapped, or
 402      *         {@code null} if this map contains no mapping for the key
 403      * @throws NullPointerException if the specified key is null
 404      * @see     #put(Object, Object)
 405      */
 406     @SuppressWarnings("unchecked")
 407     public synchronized V get(Object key) {
 408         Entry<?,?> tab[] = table;
 409         int hash = hash(key);
 410         int index = (hash & 0x7FFFFFFF) % tab.length;
 411         for (Entry<?,?> e = tab[index] ; e != null ; e = e.next) {
 412             if ((e.hash == hash) && e.key.equals(key)) {
 413                 return (V)e.value;
 414             }
 415         }
 416         return null;
 417     }
 418 
 419     /**
 420      * The maximum size of array to allocate.
 421      * Some VMs reserve some header words in an array.
 422      * Attempts to allocate larger arrays may result in
 423      * OutOfMemoryError: Requested array size exceeds VM limit
 424      */
 425     private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
 426 
 427     /**
 428      * Increases the capacity of and internally reorganizes this
 429      * hashtable, in order to accommodate and access its entries more
 430      * efficiently.  This method is called automatically when the
 431      * number of keys in the hashtable exceeds this hashtable's capacity
 432      * and load factor.
 433      */
 434     @SuppressWarnings("unchecked")
 435     protected void rehash() {
 436         int oldCapacity = table.length;
 437         Entry<?,?>[] oldMap = table;
 438 
 439         // overflow-conscious code
 440         int newCapacity = (oldCapacity << 1) + 1;
 441         if (newCapacity - MAX_ARRAY_SIZE > 0) {
 442             if (oldCapacity == MAX_ARRAY_SIZE)
 443                 // Keep running with MAX_ARRAY_SIZE buckets
 444                 return;
 445             newCapacity = MAX_ARRAY_SIZE;
 446         }
 447         Entry<?,?>[] newMap = new Entry<?,?>[newCapacity];
 448 
 449         modCount++;
 450         threshold = (int)Math.min(newCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
 451         table = newMap;
 452 
 453         for (int i = oldCapacity ; i-- > 0 ;) {
 454             for (Entry<K,V> old = (Entry<K,V>)oldMap[i] ; old != null ; ) {
 455                 Entry<K,V> e = old;
 456                 old = old.next;
 457 
 458                 int index = (e.hash & 0x7FFFFFFF) % newCapacity;
 459                 e.next = (Entry<K,V>)newMap[index];
 460                 newMap[index] = e;
 461             }
 462         }
 463     }
 464 
 465     /**
 466      * Maps the specified <code>key</code> to the specified
 467      * <code>value</code> in this hashtable. Neither the key nor the
 468      * value can be <code>null</code>. <p>
 469      *
 470      * The value can be retrieved by calling the <code>get</code> method
 471      * with a key that is equal to the original key.
 472      *
 473      * @param      key     the hashtable key
 474      * @param      value   the value
 475      * @return     the previous value of the specified key in this hashtable,
 476      *             or <code>null</code> if it did not have one
 477      * @exception  NullPointerException  if the key or value is
 478      *               <code>null</code>
 479      * @see     Object#equals(Object)
 480      * @see     #get(Object)
 481      */
 482     public synchronized V put(K key, V value) {
 483         // Make sure the value is not null
 484         if (value == null) {
 485             throw new NullPointerException();
 486         }
 487 
 488         // Makes sure the key is not already in the hashtable.
 489         Entry<?,?> tab[] = table;
 490         int hash = hash(key);
 491         int index = (hash & 0x7FFFFFFF) % tab.length;
 492         @SuppressWarnings("unchecked")
 493         Entry<K,V> entry = (Entry<K,V>)tab[index];
 494         for(; entry != null ; entry = entry.next) {
 495             if ((entry.hash == hash) && entry.key.equals(key)) {
 496                 V old = entry.value;
 497                 entry.value = value;
 498                 return old;
 499             }
 500         }
 501 
 502         modCount++;
 503         if (count >= threshold) {
 504             // Rehash the table if the threshold is exceeded
 505             rehash();
 506 
 507             tab = table;
 508             hash = hash(key);
 509             index = (hash & 0x7FFFFFFF) % tab.length;
 510         }
 511 
 512         // Creates the new entry.
 513         @SuppressWarnings("unchecked")
 514         Entry<K,V> e = (Entry<K,V>)tab[index];
 515         tab[index] = new Entry<>(hash, key, value, e);
 516         count++;
 517         return null;
 518     }
 519 
 520     /**
 521      * Removes the key (and its corresponding value) from this
 522      * hashtable. This method does nothing if the key is not in the hashtable.
 523      *
 524      * @param   key   the key that needs to be removed
 525      * @return  the value to which the key had been mapped in this hashtable,
 526      *          or <code>null</code> if the key did not have a mapping
 527      * @throws  NullPointerException  if the key is <code>null</code>
 528      */
 529     public synchronized V remove(Object key) {
 530         Entry<?,?> tab[] = table;
 531         int hash = hash(key);
 532         int index = (hash & 0x7FFFFFFF) % tab.length;
 533         @SuppressWarnings("unchecked")
 534         Entry<K,V> e = (Entry<K,V>)tab[index];
 535         for(Entry<K,V> prev = null ; e != null ; prev = e, e = e.next) {
 536             if ((e.hash == hash) && e.key.equals(key)) {
 537                 modCount++;
 538                 if (prev != null) {
 539                     prev.next = e.next;
 540                 } else {
 541                     tab[index] = e.next;
 542                 }
 543                 count--;
 544                 V oldValue = e.value;
 545                 e.value = null;
 546                 return oldValue;
 547             }
 548         }
 549         return null;
 550     }
 551 


 720         if (entrySet==null)
 721             entrySet = Collections.synchronizedSet(new EntrySet(), this);
 722         return entrySet;
 723     }
 724 
 725     private class EntrySet extends AbstractSet<Map.Entry<K,V>> {
 726         public Iterator<Map.Entry<K,V>> iterator() {
 727             return getIterator(ENTRIES);
 728         }
 729 
 730         public boolean add(Map.Entry<K,V> o) {
 731             return super.add(o);
 732         }
 733 
 734         public boolean contains(Object o) {
 735             if (!(o instanceof Map.Entry))
 736                 return false;
 737             Map.Entry<?,?> entry = (Map.Entry<?,?>)o;
 738             Object key = entry.getKey();
 739             Entry<?,?>[] tab = table;
 740             int hash = hash(key);
 741             int index = (hash & 0x7FFFFFFF) % tab.length;
 742 
 743             for (Entry<?,?> e = tab[index]; e != null; e = e.next)
 744                 if (e.hash==hash && e.equals(entry))
 745                     return true;
 746             return false;
 747         }
 748 
 749         public boolean remove(Object o) {
 750             if (!(o instanceof Map.Entry))
 751                 return false;
 752             Map.Entry<?,?> entry = (Map.Entry<?,?>) o;
 753             Object key = entry.getKey();
 754             Entry<?,?>[] tab = table;
 755             int hash = hash(key);
 756             int index = (hash & 0x7FFFFFFF) % tab.length;
 757 
 758             @SuppressWarnings("unchecked")
 759             Entry<K,V> e = (Entry<K,V>)tab[index];
 760             for(Entry<K,V> prev = null; e != null; prev = e, e = e.next) {
 761                 if (e.hash==hash && e.equals(entry)) {
 762                     modCount++;
 763                     if (prev != null)
 764                         prev.next = e.next;
 765                     else
 766                         tab[index] = e.next;
 767 
 768                     count--;
 769                     e.value = null;
 770                     return true;
 771                 }
 772             }
 773             return false;
 774         }
 775 


 870      * @see Map#hashCode()
 871      * @since 1.2
 872      */
 873     public synchronized int hashCode() {
 874         /*
 875          * This code detects the recursion caused by computing the hash code
 876          * of a self-referential hash table and prevents the stack overflow
 877          * that would otherwise result.  This allows certain 1.1-era
 878          * applets with self-referential hash tables to work.  This code
 879          * abuses the loadFactor field to do double-duty as a hashCode
 880          * in progress flag, so as not to worsen the space performance.
 881          * A negative load factor indicates that hash code computation is
 882          * in progress.
 883          */
 884         int h = 0;
 885         if (count == 0 || loadFactor < 0)
 886             return h;  // Returns zero
 887 
 888         loadFactor = -loadFactor;  // Mark hashCode computation in progress
 889         Entry<?,?>[] tab = table;
 890         for (Entry<?,?> entry : tab) {
 891             while (entry != null) {
 892                 h += entry.hashCode();
 893                 entry = entry.next;
 894             }
 895         }
 896 
 897         loadFactor = -loadFactor;  // Mark hashCode computation complete
 898 
 899         return h;
 900     }
 901 
 902     /**
 903      * Save the state of the Hashtable to a stream (i.e., serialize it).
 904      *
 905      * @serialData The <i>capacity</i> of the Hashtable (the length of the
 906      *             bucket array) is emitted (int), followed by the
 907      *             <i>size</i> of the Hashtable (the number of key-value
 908      *             mappings), followed by the key (Object) and value (Object)
 909      *             for each key-value mapping represented by the Hashtable
 910      *             The key-value mappings are emitted in no particular order.
 911      */
 912     private void writeObject(java.io.ObjectOutputStream s)
 913             throws IOException {
 914         Entry<Object, Object> entryStack = null;
 915 
 916         synchronized (this) {


 933             }
 934         }
 935 
 936         // Write out the key/value objects from the stacked entries
 937         while (entryStack != null) {
 938             s.writeObject(entryStack.key);
 939             s.writeObject(entryStack.value);
 940             entryStack = entryStack.next;
 941         }
 942     }
 943 
 944     /**
 945      * Reconstitute the Hashtable from a stream (i.e., deserialize it).
 946      */
 947     private void readObject(java.io.ObjectInputStream s)
 948          throws IOException, ClassNotFoundException
 949     {
 950         // Read in the length, threshold, and loadfactor
 951         s.defaultReadObject();
 952         
 953         // set hashMask
 954         Holder.UNSAFE.putIntVolatile(this, Holder.HASHMASK_OFFSET, 
 955                 sun.misc.Hashing.makeHashMask(this));
 956 
 957         // Read the original length of the array and number of elements
 958         int origlength = s.readInt();
 959         int elements = s.readInt();
 960 
 961         // Compute new size with a bit of room 5% to grow but
 962         // no larger than the original size.  Make the length
 963         // odd if it's large enough, this helps distribute the entries.
 964         // Guard against the length ending up zero, that's not valid.
 965         int length = (int)(elements * loadFactor) + (elements / 20) + 3;
 966         if (length > elements && (length & 1) == 0)
 967             length--;
 968         if (origlength > 0 && length > origlength)
 969             length = origlength;
 970         table = new Entry<?,?>[length];
 971         threshold = (int)Math.min(length * loadFactor, MAX_ARRAY_SIZE + 1);
 972         count = 0;
 973 
 974         // Read the number of elements and then all the key/value objects
 975         for (; elements > 0; elements--) {
 976             @SuppressWarnings("unchecked")
 977                 K key = (K)s.readObject();
 978             @SuppressWarnings("unchecked")
 979                 V value = (V)s.readObject();
 980             // synch could be eliminated for performance
 981             reconstitutionPut(table, key, value);
 982         }

 983     }
 984 
 985     /**
 986      * The put method used by readObject. This is provided because put
 987      * is overridable and should not be called in readObject since the
 988      * subclass will not yet be initialized.
 989      *
 990      * <p>This differs from the regular put method in several ways. No
 991      * checking for rehashing is necessary since the number of elements
 992      * initially in the table is known. The modCount is not incremented
 993      * because we are creating a new instance. Also, no return value
 994      * is needed.
 995      */
 996     private void reconstitutionPut(Entry<?,?>[] tab, K key, V value)
 997         throws StreamCorruptedException
 998     {
 999         if (value == null) {
1000             throw new java.io.StreamCorruptedException();
1001         }
1002         // Makes sure the key is not already in the hashtable.
1003         // This should not happen in deserialized version.
1004         int hash = hash(key);
1005         int index = (hash & 0x7FFFFFFF) % tab.length;
1006         for (Entry<?,?> e = tab[index] ; e != null ; e = e.next) {
1007             if ((e.hash == hash) && e.key.equals(key)) {
1008                 throw new java.io.StreamCorruptedException();
1009             }
1010         }
1011         // Creates the new entry.
1012         @SuppressWarnings("unchecked")
1013             Entry<K,V> e = (Entry<K,V>)tab[index];
1014         tab[index] = new Entry<>(hash, key, value, e);
1015         count++;
1016     }
1017 
1018     /**
1019      * Hashtable bucket collision list entry
1020      */
1021     private static class Entry<K,V> implements Map.Entry<K,V> {
1022         final int hash;
1023         K key;
1024         V value;
1025         Entry<K,V> next;
1026 
1027         protected Entry(int hash, K key, V value, Entry<K,V> next) {
1028             this.hash = hash;
1029             this.key =  key;
1030             this.value = value;
1031             this.next = next;
1032         }
1033 
1034         @SuppressWarnings("unchecked")
1035         protected Object clone() {
1036             return new Entry<>(hash, key, value,
1037                                   (next==null ? null : (Entry<K,V>) next.clone()));
1038         }
1039 
1040         // Map.Entry Ops
1041 
1042         public K getKey() {