170 * The load factor for the hash table.
171 */
172 private final float loadFactor;
173
174 /**
175 * Reference queue for cleared WeakEntries
176 */
177 private final ReferenceQueue<Object> queue = new ReferenceQueue<>();
178
179 /**
180 * The number of times this WeakHashMap has been structurally modified.
181 * Structural modifications are those that change the number of
182 * mappings in the map or otherwise modify its internal structure
183 * (e.g., rehash). This field is used to make iterators on
184 * Collection-views of the map fail-fast.
185 *
186 * @see ConcurrentModificationException
187 */
188 int modCount;
189
190 /**
191 * A randomizing value associated with this instance that is applied to
192 * hash code of keys to make hash collisions harder to find.
193 */
194 transient final int hashSeed = sun.misc.Hashing.randomHashSeed(this);
195
196 @SuppressWarnings("unchecked")
197 private Entry<K,V>[] newTable(int n) {
198 return (Entry<K,V>[]) new Entry<?,?>[n];
199 }
200
201 /**
202 * Constructs a new, empty <tt>WeakHashMap</tt> with the given initial
203 * capacity and the given load factor.
204 *
205 * @param initialCapacity The initial capacity of the <tt>WeakHashMap</tt>
206 * @param loadFactor The load factor of the <tt>WeakHashMap</tt>
207 * @throws IllegalArgumentException if the initial capacity is negative,
208 * or if the load factor is nonpositive.
209 */
210 public WeakHashMap(int initialCapacity, float loadFactor) {
211 if (initialCapacity < 0)
212 throw new IllegalArgumentException("Illegal Initial Capacity: "+
213 initialCapacity);
214 if (initialCapacity > MAXIMUM_CAPACITY)
215 initialCapacity = MAXIMUM_CAPACITY;
216
217 if (loadFactor <= 0 || Float.isNaN(loadFactor))
218 throw new IllegalArgumentException("Illegal Load factor: "+
219 loadFactor);
220 int capacity = 1;
221 while (capacity < initialCapacity)
222 capacity <<= 1;
223 table = newTable(capacity);
224 this.loadFactor = loadFactor;
225 threshold = (int)(capacity * loadFactor);
226 }
227
228 /**
229 * Constructs a new, empty <tt>WeakHashMap</tt> with the given initial
230 * capacity and the default load factor (0.75).
231 *
232 * @param initialCapacity The initial capacity of the <tt>WeakHashMap</tt>
233 * @throws IllegalArgumentException if the initial capacity is negative
234 */
235 public WeakHashMap(int initialCapacity) {
236 this(initialCapacity, DEFAULT_LOAD_FACTOR);
237 }
238
239 /**
240 * Constructs a new, empty <tt>WeakHashMap</tt> with the default initial
241 * capacity (16) and load factor (0.75).
242 */
243 public WeakHashMap() {
244 this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR);
245 }
281 static Object unmaskNull(Object key) {
282 return (key == NULL_KEY) ? null : key;
283 }
284
285 /**
286 * Checks for equality of non-null reference x and possibly-null y. By
287 * default uses Object.equals.
288 */
289 private static boolean eq(Object x, Object y) {
290 return x == y || x.equals(y);
291 }
292
293 /**
294 * Retrieve object hash code and applies a supplemental hash function to the
295 * result hash, which defends against poor quality hash functions. This is
296 * critical because HashMap uses power-of-two length hash tables, that
297 * otherwise encounter collisions for hashCodes that do not differ
298 * in lower bits.
299 */
300 final int hash(Object k) {
301 if (k instanceof String) {
302 return ((String) k).hash32();
303 }
304 int h = hashSeed ^ k.hashCode();
305
306 // This function ensures that hashCodes that differ only by
307 // constant multiples at each bit position have a bounded
308 // number of collisions (approximately 8 at default load factor).
309 h ^= (h >>> 20) ^ (h >>> 12);
310 return h ^ (h >>> 7) ^ (h >>> 4);
311 }
312
313 /**
314 * Returns index for hash code h.
315 */
316 private static int indexFor(int h, int length) {
317 return h & (length-1);
318 }
319
320 /**
321 * Expunges stale entries from the table.
322 */
323 private void expungeStaleEntries() {
|
170 * The load factor for the hash table.
171 */
172 private final float loadFactor;
173
174 /**
175 * Reference queue for cleared WeakEntries
176 */
177 private final ReferenceQueue<Object> queue = new ReferenceQueue<>();
178
179 /**
180 * The number of times this WeakHashMap has been structurally modified.
181 * Structural modifications are those that change the number of
182 * mappings in the map or otherwise modify its internal structure
183 * (e.g., rehash). This field is used to make iterators on
184 * Collection-views of the map fail-fast.
185 *
186 * @see ConcurrentModificationException
187 */
188 int modCount;
189
190 private static class Holder {
191 static final boolean USE_HASHSEED;
192
193 static {
194 String hashSeedProp = java.security.AccessController.doPrivileged(
195 new sun.security.action.GetPropertyAction(
196 "jdk.map.useRandomSeed"));
197 boolean localBool = (null != hashSeedProp)
198 ? Boolean.parseBoolean(hashSeedProp) : false;
199 USE_HASHSEED = localBool;
200 }
201 }
202
203 /**
204 * A randomizing value associated with this instance that is applied to
205 * hash code of keys to make hash collisions harder to find.
206 *
207 * Non-final so it can be set lazily, but be sure not to set more than once.
208 */
209 transient int hashSeed;
210
211 /**
212 * Initialize the hashing mask value.
213 */
214 final void initHashSeed() {
215 if (sun.misc.VM.isBooted() && Holder.USE_HASHSEED) {
216 // Do not set hashSeed more than once!
217 // assert hashSeed == 0;
218 hashSeed = sun.misc.Hashing.randomHashSeed(this);
219 }
220 }
221
222 @SuppressWarnings("unchecked")
223 private Entry<K,V>[] newTable(int n) {
224 return (Entry<K,V>[]) new Entry<?,?>[n];
225 }
226
227 /**
228 * Constructs a new, empty <tt>WeakHashMap</tt> with the given initial
229 * capacity and the given load factor.
230 *
231 * @param initialCapacity The initial capacity of the <tt>WeakHashMap</tt>
232 * @param loadFactor The load factor of the <tt>WeakHashMap</tt>
233 * @throws IllegalArgumentException if the initial capacity is negative,
234 * or if the load factor is nonpositive.
235 */
236 public WeakHashMap(int initialCapacity, float loadFactor) {
237 if (initialCapacity < 0)
238 throw new IllegalArgumentException("Illegal Initial Capacity: "+
239 initialCapacity);
240 if (initialCapacity > MAXIMUM_CAPACITY)
241 initialCapacity = MAXIMUM_CAPACITY;
242
243 if (loadFactor <= 0 || Float.isNaN(loadFactor))
244 throw new IllegalArgumentException("Illegal Load factor: "+
245 loadFactor);
246 int capacity = 1;
247 while (capacity < initialCapacity)
248 capacity <<= 1;
249 table = newTable(capacity);
250 this.loadFactor = loadFactor;
251 threshold = (int)(capacity * loadFactor);
252 initHashSeed();
253 }
254
255 /**
256 * Constructs a new, empty <tt>WeakHashMap</tt> with the given initial
257 * capacity and the default load factor (0.75).
258 *
259 * @param initialCapacity The initial capacity of the <tt>WeakHashMap</tt>
260 * @throws IllegalArgumentException if the initial capacity is negative
261 */
262 public WeakHashMap(int initialCapacity) {
263 this(initialCapacity, DEFAULT_LOAD_FACTOR);
264 }
265
266 /**
267 * Constructs a new, empty <tt>WeakHashMap</tt> with the default initial
268 * capacity (16) and load factor (0.75).
269 */
270 public WeakHashMap() {
271 this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR);
272 }
308 static Object unmaskNull(Object key) {
309 return (key == NULL_KEY) ? null : key;
310 }
311
312 /**
313 * Checks for equality of non-null reference x and possibly-null y. By
314 * default uses Object.equals.
315 */
316 private static boolean eq(Object x, Object y) {
317 return x == y || x.equals(y);
318 }
319
320 /**
321 * Retrieve object hash code and applies a supplemental hash function to the
322 * result hash, which defends against poor quality hash functions. This is
323 * critical because HashMap uses power-of-two length hash tables, that
324 * otherwise encounter collisions for hashCodes that do not differ
325 * in lower bits.
326 */
327 final int hash(Object k) {
328 int h = hashSeed ^ k.hashCode();
329
330 // This function ensures that hashCodes that differ only by
331 // constant multiples at each bit position have a bounded
332 // number of collisions (approximately 8 at default load factor).
333 h ^= (h >>> 20) ^ (h >>> 12);
334 return h ^ (h >>> 7) ^ (h >>> 4);
335 }
336
337 /**
338 * Returns index for hash code h.
339 */
340 private static int indexFor(int h, int length) {
341 return h & (length-1);
342 }
343
344 /**
345 * Expunges stale entries from the table.
346 */
347 private void expungeStaleEntries() {
|