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

Print this page




 151     /**
 152      * The load factor for the hashtable.
 153      *
 154      * @serial
 155      */
 156     private float loadFactor;
 157 
 158     /**
 159      * The number of times this Hashtable has been structurally modified
 160      * Structural modifications are those that change the number of entries in
 161      * the Hashtable or otherwise modify its internal structure (e.g.,
 162      * rehash).  This field is used to make iterators on Collection-views of
 163      * the Hashtable fail-fast.  (See ConcurrentModificationException).
 164      */
 165     private transient int modCount = 0;
 166 
 167     /** use serialVersionUID from JDK 1.0.2 for interoperability */
 168     private static final long serialVersionUID = 1421746759512286392L;
 169 
 170     private static class Holder {
 171             // Unsafe mechanics
 172         /**
 173          *
 174          */
 175         static final sun.misc.Unsafe UNSAFE;
 176 
 177         /**
 178          * Offset of "final" hashSeed field we must set in
 179          * readObject() method.
 180          */
 181         static final long HASHSEED_OFFSET;
 182 
 183         static {
 184             try {
 185                 UNSAFE = sun.misc.Unsafe.getUnsafe();
 186                 HASHSEED_OFFSET = UNSAFE.objectFieldOffset(
 187                     Hashtable.class.getDeclaredField("hashSeed"));
 188             } catch (NoSuchFieldException | SecurityException e) {
 189                 throw new InternalError("Failed to record hashSeed offset", e);
 190             }
 191         }
 192     }
 193 
 194     /**
 195      * A randomizing value associated with this instance that is applied to
 196      * hash code of keys to make hash collisions harder to find.


 197      */
 198     transient final int hashSeed = sun.misc.Hashing.randomHashSeed(this);
 199 
 200     private int hash(Object k) {
 201         if (k instanceof String) {
 202             return ((String)k).hash32();






 203         }
 204 
 205         int h = hashSeed ^ k.hashCode();
 206 
 207         // This function ensures that hashCodes that differ only by
 208         // constant multiples at each bit position have a bounded
 209         // number of collisions (approximately 8 at default load factor).
 210         h ^= (h >>> 20) ^ (h >>> 12);
 211         return h ^ (h >>> 7) ^ (h >>> 4);
 212     }
 213 
 214     /**
 215      * Constructs a new, empty hashtable with the specified initial
 216      * capacity and the specified load factor.
 217      *
 218      * @param      initialCapacity   the initial capacity of the hashtable.
 219      * @param      loadFactor        the load factor of the hashtable.
 220      * @exception  IllegalArgumentException  if the initial capacity is less
 221      *             than zero, or if the load factor is nonpositive.
 222      */
 223     public Hashtable(int initialCapacity, float loadFactor) {
 224         if (initialCapacity < 0)
 225             throw new IllegalArgumentException("Illegal Capacity: "+
 226                                                initialCapacity);
 227         if (loadFactor <= 0 || Float.isNaN(loadFactor))
 228             throw new IllegalArgumentException("Illegal Load: "+loadFactor);
 229 
 230         if (initialCapacity==0)
 231             initialCapacity = 1;
 232         this.loadFactor = loadFactor;
 233         table = new Entry<?,?>[initialCapacity];
 234         threshold = (int)Math.min(initialCapacity * loadFactor, MAX_ARRAY_SIZE + 1);

 235     }
 236 
 237     /**
 238      * Constructs a new, empty hashtable with the specified initial capacity
 239      * and default load factor (0.75).
 240      *
 241      * @param     initialCapacity   the initial capacity of the hashtable.
 242      * @exception IllegalArgumentException if the initial capacity is less
 243      *              than zero.
 244      */
 245     public Hashtable(int initialCapacity) {
 246         this(initialCapacity, 0.75f);
 247     }
 248 
 249     /**
 250      * Constructs a new, empty hashtable with a default initial capacity (11)
 251      * and load factor (0.75).
 252      */
 253     public Hashtable() {
 254         this(11, 0.75f);


1169             }
1170         }
1171 
1172         // Write out the key/value objects from the stacked entries
1173         while (entryStack != null) {
1174             s.writeObject(entryStack.key);
1175             s.writeObject(entryStack.value);
1176             entryStack = entryStack.next;
1177         }
1178     }
1179 
1180     /**
1181      * Reconstitute the Hashtable from a stream (i.e., deserialize it).
1182      */
1183     private void readObject(java.io.ObjectInputStream s)
1184          throws IOException, ClassNotFoundException
1185     {
1186         // Read in the length, threshold, and loadfactor
1187         s.defaultReadObject();
1188 
1189         // set hashMask
1190         Holder.UNSAFE.putIntVolatile(this, Holder.HASHSEED_OFFSET,
1191                 sun.misc.Hashing.randomHashSeed(this));
1192 
1193         // Read the original length of the array and number of elements
1194         int origlength = s.readInt();
1195         int elements = s.readInt();
1196 
1197         // Compute new size with a bit of room 5% to grow but
1198         // no larger than the original size.  Make the length
1199         // odd if it's large enough, this helps distribute the entries.
1200         // Guard against the length ending up zero, that's not valid.
1201         int length = (int)(elements * loadFactor) + (elements / 20) + 3;
1202         if (length > elements && (length & 1) == 0)
1203             length--;
1204         if (origlength > 0 && length > origlength)
1205             length = origlength;
1206         table = new Entry<?,?>[length];
1207         threshold = (int)Math.min(length * loadFactor, MAX_ARRAY_SIZE + 1);
1208         count = 0;

1209 
1210         // Read the number of elements and then all the key/value objects
1211         for (; elements > 0; elements--) {
1212             @SuppressWarnings("unchecked")
1213                 K key = (K)s.readObject();
1214             @SuppressWarnings("unchecked")
1215                 V value = (V)s.readObject();
1216             // synch could be eliminated for performance
1217             reconstitutionPut(table, key, value);
1218         }
1219     }
1220 
1221     /**
1222      * The put method used by readObject. This is provided because put
1223      * is overridable and should not be called in readObject since the
1224      * subclass will not yet be initialized.
1225      *
1226      * <p>This differs from the regular put method in several ways. No
1227      * checking for rehashing is necessary since the number of elements
1228      * initially in the table is known. The modCount is not incremented




 151     /**
 152      * The load factor for the hashtable.
 153      *
 154      * @serial
 155      */
 156     private float loadFactor;
 157 
 158     /**
 159      * The number of times this Hashtable has been structurally modified
 160      * Structural modifications are those that change the number of entries in
 161      * the Hashtable or otherwise modify its internal structure (e.g.,
 162      * rehash).  This field is used to make iterators on Collection-views of
 163      * the Hashtable fail-fast.  (See ConcurrentModificationException).
 164      */
 165     private transient int modCount = 0;
 166 
 167     /** use serialVersionUID from JDK 1.0.2 for interoperability */
 168     private static final long serialVersionUID = 1421746759512286392L;
 169 
 170     private static class Holder {
 171         static final boolean USE_HASHSEED;










 172 
 173         static {
 174             String hashSeedProp = java.security.AccessController.doPrivileged(
 175                     new sun.security.action.GetPropertyAction(
 176                         "jdk.map.useRandomSeed"));
 177             boolean localBool = (null != hashSeedProp)
 178                     ? Boolean.parseBoolean(hashSeedProp) : false;
 179             USE_HASHSEED = localBool;

 180         }
 181     }
 182 
 183     /**
 184      * A randomizing value associated with this instance that is applied to
 185      * hash code of keys to make hash collisions harder to find.
 186      *
 187      * Non-final so it can be set lazily, but be sure not to set more than once.
 188      */
 189     transient int hashSeed;
 190 
 191     /**
 192      * Initialize the hashing mask value.
 193      */
 194     final void initHashSeed() {
 195         if (sun.misc.VM.isBooted() && Holder.USE_HASHSEED) {
 196             // Do not set hashSeed more than once!
 197             // assert hashSeed == 0;
 198             hashSeed = sun.misc.Hashing.randomHashSeed(this);
 199         }
 200     }
 201 
 202     private int hash(Object k) {
 203         return hashSeed ^ k.hashCode();





 204     }
 205 
 206     /**
 207      * Constructs a new, empty hashtable with the specified initial
 208      * capacity and the specified load factor.
 209      *
 210      * @param      initialCapacity   the initial capacity of the hashtable.
 211      * @param      loadFactor        the load factor of the hashtable.
 212      * @exception  IllegalArgumentException  if the initial capacity is less
 213      *             than zero, or if the load factor is nonpositive.
 214      */
 215     public Hashtable(int initialCapacity, float loadFactor) {
 216         if (initialCapacity < 0)
 217             throw new IllegalArgumentException("Illegal Capacity: "+
 218                                                initialCapacity);
 219         if (loadFactor <= 0 || Float.isNaN(loadFactor))
 220             throw new IllegalArgumentException("Illegal Load: "+loadFactor);
 221 
 222         if (initialCapacity==0)
 223             initialCapacity = 1;
 224         this.loadFactor = loadFactor;
 225         table = new Entry<?,?>[initialCapacity];
 226         threshold = (int)Math.min(initialCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
 227         initHashSeed();
 228     }
 229 
 230     /**
 231      * Constructs a new, empty hashtable with the specified initial capacity
 232      * and default load factor (0.75).
 233      *
 234      * @param     initialCapacity   the initial capacity of the hashtable.
 235      * @exception IllegalArgumentException if the initial capacity is less
 236      *              than zero.
 237      */
 238     public Hashtable(int initialCapacity) {
 239         this(initialCapacity, 0.75f);
 240     }
 241 
 242     /**
 243      * Constructs a new, empty hashtable with a default initial capacity (11)
 244      * and load factor (0.75).
 245      */
 246     public Hashtable() {
 247         this(11, 0.75f);


1162             }
1163         }
1164 
1165         // Write out the key/value objects from the stacked entries
1166         while (entryStack != null) {
1167             s.writeObject(entryStack.key);
1168             s.writeObject(entryStack.value);
1169             entryStack = entryStack.next;
1170         }
1171     }
1172 
1173     /**
1174      * Reconstitute the Hashtable from a stream (i.e., deserialize it).
1175      */
1176     private void readObject(java.io.ObjectInputStream s)
1177          throws IOException, ClassNotFoundException
1178     {
1179         // Read in the length, threshold, and loadfactor
1180         s.defaultReadObject();
1181 




1182         // Read the original length of the array and number of elements
1183         int origlength = s.readInt();
1184         int elements = s.readInt();
1185 
1186         // Compute new size with a bit of room 5% to grow but
1187         // no larger than the original size.  Make the length
1188         // odd if it's large enough, this helps distribute the entries.
1189         // Guard against the length ending up zero, that's not valid.
1190         int length = (int)(elements * loadFactor) + (elements / 20) + 3;
1191         if (length > elements && (length & 1) == 0)
1192             length--;
1193         if (origlength > 0 && length > origlength)
1194             length = origlength;
1195         table = new Entry<?,?>[length];
1196         threshold = (int)Math.min(length * loadFactor, MAX_ARRAY_SIZE + 1);
1197         count = 0;
1198         initHashSeed();
1199 
1200         // Read the number of elements and then all the key/value objects
1201         for (; elements > 0; elements--) {
1202             @SuppressWarnings("unchecked")
1203                 K key = (K)s.readObject();
1204             @SuppressWarnings("unchecked")
1205                 V value = (V)s.readObject();
1206             // synch could be eliminated for performance
1207             reconstitutionPut(table, key, value);
1208         }
1209     }
1210 
1211     /**
1212      * The put method used by readObject. This is provided because put
1213      * is overridable and should not be called in readObject since the
1214      * subclass will not yet be initialized.
1215      *
1216      * <p>This differs from the regular put method in several ways. No
1217      * checking for rehashing is necessary since the number of elements
1218      * initially in the table is known. The modCount is not incremented