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             if (k.getClass() == String.class) {
 244                 return sun.misc.Hashing.stringHash32((String) k);
 245             } else {
 246                 int h = hashSeed ^ k.hashCode();
 247  
 248                 // This function ensures that hashCodes that differ only by
 249                 // constant multiples at each bit position have a bounded
 250                 // number of collisions (approximately 8 at default load factor).
 251                 h ^= (h >>> 20) ^ (h >>> 12);
 252                 return h ^ (h >>> 7) ^ (h >>> 4);
 253              }
 254         } else  {
 255             return k.hashCode();
 256         }
 257     }
 258 
 259     /**
 260      * Constructs a new, empty hashtable with the specified initial
 261      * capacity and the specified load factor.
 262      *
 263      * @param      initialCapacity   the initial capacity of the hashtable.
 264      * @param      loadFactor        the load factor of the hashtable.
 265      * @exception  IllegalArgumentException  if the initial capacity is less
 266      *             than zero, or if the load factor is nonpositive.
 267      */
 268     public Hashtable(int initialCapacity, float loadFactor) {
 269         if (initialCapacity < 0)
 270             throw new IllegalArgumentException("Illegal Capacity: "+
 271                                                initialCapacity);
 272         if (loadFactor <= 0 || Float.isNaN(loadFactor))
 273             throw new IllegalArgumentException("Illegal Load: "+loadFactor);
 274 
 275         if (initialCapacity==0)
 276             initialCapacity = 1;
 277         this.loadFactor = loadFactor;
 278         table = new Entry[initialCapacity];
 279         threshold = (int)Math.min(initialCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
 280         useAltHashing = sun.misc.VM.isBooted() &&
 281                 (initialCapacity >= Holder.ALTERNATE_HASHING_THRESHOLD);
 282     }
 283 
 284     /**
 285      * Constructs a new, empty hashtable with the specified initial capacity
 286      * and default load factor (0.75).
 287      *
 288      * @param     initialCapacity   the initial capacity of the hashtable.
 289      * @exception IllegalArgumentException if the initial capacity is less
 290      *              than zero.
 291      */
 292     public Hashtable(int initialCapacity) {
 293         this(initialCapacity, 0.75f);
 294     }
 295 
 296     /**
 297      * Constructs a new, empty hashtable with a default initial capacity (11)
 298      * and load factor (0.75).
 299      */
 300     public Hashtable() {
 301         this(11, 0.75f);


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


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


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


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

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