src/share/classes/java/util/WeakHashMap.java

Print this page




 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() {