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
|