< prev index next >

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

Print this page

        

*** 32,122 **** import java.util.function.BiFunction; import java.util.function.Consumer; /** ! * Hash table based implementation of the <tt>Map</tt> interface, with * <em>weak keys</em>. ! * An entry in a <tt>WeakHashMap</tt> will automatically be removed when * its key is no longer in ordinary use. More precisely, the presence of a * mapping for a given key will not prevent the key from being discarded by the * garbage collector, that is, made finalizable, finalized, and then reclaimed. * When a key has been discarded its entry is effectively removed from the map, ! * so this class behaves somewhat differently from other <tt>Map</tt> * implementations. * * <p> Both null values and the null key are supported. This class has ! * performance characteristics similar to those of the <tt>HashMap</tt> * class, and has the same efficiency parameters of <em>initial capacity</em> * and <em>load factor</em>. * * <p> Like most collection classes, this class is not synchronized. ! * A synchronized <tt>WeakHashMap</tt> may be constructed using the * {@link Collections#synchronizedMap Collections.synchronizedMap} * method. * * <p> This class is intended primarily for use with key objects whose ! * <tt>equals</tt> methods test for object identity using the ! * <tt>==</tt> operator. Once such a key is discarded it can never be * recreated, so it is impossible to do a lookup of that key in a ! * <tt>WeakHashMap</tt> at some later time and be surprised that its entry * has been removed. This class will work perfectly well with key objects ! * whose <tt>equals</tt> methods are not based upon object identity, such ! * as <tt>String</tt> instances. With such recreatable key objects, ! * however, the automatic removal of <tt>WeakHashMap</tt> entries whose * keys have been discarded may prove to be confusing. * ! * <p> The behavior of the <tt>WeakHashMap</tt> class depends in part upon * the actions of the garbage collector, so several familiar (though not ! * required) <tt>Map</tt> invariants do not hold for this class. Because * the garbage collector may discard keys at any time, a ! * <tt>WeakHashMap</tt> may behave as though an unknown thread is silently * removing entries. In particular, even if you synchronize on a ! * <tt>WeakHashMap</tt> instance and invoke none of its mutator methods, it ! * is possible for the <tt>size</tt> method to return smaller values over ! * time, for the <tt>isEmpty</tt> method to return <tt>false</tt> and ! * then <tt>true</tt>, for the <tt>containsKey</tt> method to return ! * <tt>true</tt> and later <tt>false</tt> for a given key, for the ! * <tt>get</tt> method to return a value for a given key but later return ! * <tt>null</tt>, for the <tt>put</tt> method to return ! * <tt>null</tt> and the <tt>remove</tt> method to return ! * <tt>false</tt> for a key that previously appeared to be in the map, and * for successive examinations of the key set, the value collection, and * the entry set to yield successively smaller numbers of elements. * ! * <p> Each key object in a <tt>WeakHashMap</tt> is stored indirectly as * the referent of a weak reference. Therefore a key will automatically be * removed only after the weak references to it, both inside and outside of the * map, have been cleared by the garbage collector. * * <p> <strong>Implementation note:</strong> The value objects in a ! * <tt>WeakHashMap</tt> are held by ordinary strong references. Thus care * should be taken to ensure that value objects do not strongly refer to their * own keys, either directly or indirectly, since that will prevent the keys * from being discarded. Note that a value object may refer indirectly to its ! * key via the <tt>WeakHashMap</tt> itself; that is, a value object may * strongly refer to some other key object whose associated value object, in * turn, strongly refers to the key of the first value object. If the values * in the map do not rely on the map holding strong references to them, one way * to deal with this is to wrap values themselves within ! * <tt>WeakReferences</tt> before ! * inserting, as in: <tt>m.put(key, new WeakReference(value))</tt>, ! * and then unwrapping upon each <tt>get</tt>. * ! * <p>The iterators returned by the <tt>iterator</tt> method of the collections * returned by all of this class's "collection view methods" are * <i>fail-fast</i>: if the map is structurally modified at any time after the * iterator is created, in any way except through the iterator's own ! * <tt>remove</tt> method, the iterator will throw a {@link * ConcurrentModificationException}. Thus, in the face of concurrent * modification, the iterator fails quickly and cleanly, rather than risking * arbitrary, non-deterministic behavior at an undetermined time in the future. * * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed * as it is, generally speaking, impossible to make any hard guarantees in the * presence of unsynchronized concurrent modification. Fail-fast iterators ! * throw <tt>ConcurrentModificationException</tt> on a best-effort basis. * Therefore, it would be wrong to write a program that depended on this * exception for its correctness: <i>the fail-fast behavior of iterators * should be used only to detect bugs.</i> * * <p>This class is a member of the --- 32,122 ---- import java.util.function.BiFunction; import java.util.function.Consumer; /** ! * Hash table based implementation of the {@code Map} interface, with * <em>weak keys</em>. ! * An entry in a {@code WeakHashMap} will automatically be removed when * its key is no longer in ordinary use. More precisely, the presence of a * mapping for a given key will not prevent the key from being discarded by the * garbage collector, that is, made finalizable, finalized, and then reclaimed. * When a key has been discarded its entry is effectively removed from the map, ! * so this class behaves somewhat differently from other {@code Map} * implementations. * * <p> Both null values and the null key are supported. This class has ! * performance characteristics similar to those of the {@code HashMap} * class, and has the same efficiency parameters of <em>initial capacity</em> * and <em>load factor</em>. * * <p> Like most collection classes, this class is not synchronized. ! * A synchronized {@code WeakHashMap} may be constructed using the * {@link Collections#synchronizedMap Collections.synchronizedMap} * method. * * <p> This class is intended primarily for use with key objects whose ! * {@code equals} methods test for object identity using the ! * {@code ==} operator. Once such a key is discarded it can never be * recreated, so it is impossible to do a lookup of that key in a ! * {@code WeakHashMap} at some later time and be surprised that its entry * has been removed. This class will work perfectly well with key objects ! * whose {@code equals} methods are not based upon object identity, such ! * as {@code String} instances. With such recreatable key objects, ! * however, the automatic removal of {@code WeakHashMap} entries whose * keys have been discarded may prove to be confusing. * ! * <p> The behavior of the {@code WeakHashMap} class depends in part upon * the actions of the garbage collector, so several familiar (though not ! * required) {@code Map} invariants do not hold for this class. Because * the garbage collector may discard keys at any time, a ! * {@code WeakHashMap} may behave as though an unknown thread is silently * removing entries. In particular, even if you synchronize on a ! * {@code WeakHashMap} instance and invoke none of its mutator methods, it ! * is possible for the {@code size} method to return smaller values over ! * time, for the {@code isEmpty} method to return {@code false} and ! * then {@code true}, for the {@code containsKey} method to return ! * {@code true} and later {@code false} for a given key, for the ! * {@code get} method to return a value for a given key but later return ! * {@code null}, for the {@code put} method to return ! * {@code null} and the {@code remove} method to return ! * {@code false} for a key that previously appeared to be in the map, and * for successive examinations of the key set, the value collection, and * the entry set to yield successively smaller numbers of elements. * ! * <p> Each key object in a {@code WeakHashMap} is stored indirectly as * the referent of a weak reference. Therefore a key will automatically be * removed only after the weak references to it, both inside and outside of the * map, have been cleared by the garbage collector. * * <p> <strong>Implementation note:</strong> The value objects in a ! * {@code WeakHashMap} are held by ordinary strong references. Thus care * should be taken to ensure that value objects do not strongly refer to their * own keys, either directly or indirectly, since that will prevent the keys * from being discarded. Note that a value object may refer indirectly to its ! * key via the {@code WeakHashMap} itself; that is, a value object may * strongly refer to some other key object whose associated value object, in * turn, strongly refers to the key of the first value object. If the values * in the map do not rely on the map holding strong references to them, one way * to deal with this is to wrap values themselves within ! * {@code WeakReferences} before ! * inserting, as in: {@code m.put(key, new WeakReference(value))}, ! * and then unwrapping upon each {@code get}. * ! * <p>The iterators returned by the {@code iterator} method of the collections * returned by all of this class's "collection view methods" are * <i>fail-fast</i>: if the map is structurally modified at any time after the * iterator is created, in any way except through the iterator's own ! * {@code remove} method, the iterator will throw a {@link * ConcurrentModificationException}. Thus, in the face of concurrent * modification, the iterator fails quickly and cleanly, rather than risking * arbitrary, non-deterministic behavior at an undetermined time in the future. * * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed * as it is, generally speaking, impossible to make any hard guarantees in the * presence of unsynchronized concurrent modification. Fail-fast iterators ! * throw {@code ConcurrentModificationException} on a best-effort basis. * Therefore, it would be wrong to write a program that depended on this * exception for its correctness: <i>the fail-fast behavior of iterators * should be used only to detect bugs.</i> * * <p>This class is a member of the
*** 194,208 **** private Entry<K,V>[] newTable(int n) { return (Entry<K,V>[]) new Entry<?,?>[n]; } /** ! * Constructs a new, empty <tt>WeakHashMap</tt> with the given initial * capacity and the given load factor. * ! * @param initialCapacity The initial capacity of the <tt>WeakHashMap</tt> ! * @param loadFactor The load factor of the <tt>WeakHashMap</tt> * @throws IllegalArgumentException if the initial capacity is negative, * or if the load factor is nonpositive. */ public WeakHashMap(int initialCapacity, float loadFactor) { if (initialCapacity < 0) --- 194,208 ---- private Entry<K,V>[] newTable(int n) { return (Entry<K,V>[]) new Entry<?,?>[n]; } /** ! * Constructs a new, empty {@code WeakHashMap} with the given initial * capacity and the given load factor. * ! * @param initialCapacity The initial capacity of the {@code WeakHashMap} ! * @param loadFactor The load factor of the {@code WeakHashMap} * @throws IllegalArgumentException if the initial capacity is negative, * or if the load factor is nonpositive. */ public WeakHashMap(int initialCapacity, float loadFactor) { if (initialCapacity < 0)
*** 221,251 **** this.loadFactor = loadFactor; threshold = (int)(capacity * loadFactor); } /** ! * Constructs a new, empty <tt>WeakHashMap</tt> with the given initial * capacity and the default load factor (0.75). * ! * @param initialCapacity The initial capacity of the <tt>WeakHashMap</tt> * @throws IllegalArgumentException if the initial capacity is negative */ public WeakHashMap(int initialCapacity) { this(initialCapacity, DEFAULT_LOAD_FACTOR); } /** ! * Constructs a new, empty <tt>WeakHashMap</tt> with the default initial * capacity (16) and load factor (0.75). */ public WeakHashMap() { this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR); } /** ! * Constructs a new <tt>WeakHashMap</tt> with the same mappings as the ! * specified map. The <tt>WeakHashMap</tt> is created with the default * load factor (0.75) and an initial capacity sufficient to hold the * mappings in the specified map. * * @param m the map whose mappings are to be placed in this map * @throws NullPointerException if the specified map is null --- 221,251 ---- this.loadFactor = loadFactor; threshold = (int)(capacity * loadFactor); } /** ! * Constructs a new, empty {@code WeakHashMap} with the given initial * capacity and the default load factor (0.75). * ! * @param initialCapacity The initial capacity of the {@code WeakHashMap} * @throws IllegalArgumentException if the initial capacity is negative */ public WeakHashMap(int initialCapacity) { this(initialCapacity, DEFAULT_LOAD_FACTOR); } /** ! * Constructs a new, empty {@code WeakHashMap} with the default initial * capacity (16) and load factor (0.75). */ public WeakHashMap() { this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR); } /** ! * Constructs a new {@code WeakHashMap} with the same mappings as the ! * specified map. The {@code WeakHashMap} is created with the default * load factor (0.75) and an initial capacity sufficient to hold the * mappings in the specified map. * * @param m the map whose mappings are to be placed in this map * @throws NullPointerException if the specified map is null
*** 363,373 **** expungeStaleEntries(); return size; } /** ! * Returns <tt>true</tt> if this map contains no key-value mappings. * This result is a snapshot, and may not reflect unprocessed * entries that will be removed before next attempted access * because they are no longer referenced. */ public boolean isEmpty() { --- 363,373 ---- expungeStaleEntries(); return size; } /** ! * Returns {@code true} if this map contains no key-value mappings. * This result is a snapshot, and may not reflect unprocessed * entries that will be removed before next attempted access * because they are no longer referenced. */ public boolean isEmpty() {
*** 404,419 **** } return null; } /** ! * Returns <tt>true</tt> if this map contains a mapping for the * specified key. * * @param key The key whose presence in this map is to be tested ! * @return <tt>true</tt> if there is a mapping for <tt>key</tt>; ! * <tt>false</tt> otherwise */ public boolean containsKey(Object key) { return getEntry(key) != null; } --- 404,419 ---- } return null; } /** ! * Returns {@code true} if this map contains a mapping for the * specified key. * * @param key The key whose presence in this map is to be tested ! * @return {@code true} if there is a mapping for {@code key}; ! * {@code false} otherwise */ public boolean containsKey(Object key) { return getEntry(key) != null; }
*** 437,450 **** * If the map previously contained a mapping for this key, the old * value is replaced. * * @param key key with which the specified value is to be associated. * @param value value to be associated with the specified key. ! * @return the previous value associated with <tt>key</tt>, or ! * <tt>null</tt> if there was no mapping for <tt>key</tt>. ! * (A <tt>null</tt> return can also indicate that the map ! * previously associated <tt>null</tt> with <tt>key</tt>.) */ public V put(K key, V value) { Object k = maskNull(key); int h = hash(k); Entry<K,V>[] tab = getTable(); --- 437,450 ---- * If the map previously contained a mapping for this key, the old * value is replaced. * * @param key key with which the specified value is to be associated. * @param value value to be associated with the specified key. ! * @return the previous value associated with {@code key}, or ! * {@code null} if there was no mapping for {@code key}. ! * (A {@code null} return can also indicate that the map ! * previously associated {@code null} with {@code key}.) */ public V put(K key, V value) { Object k = maskNull(key); int h = hash(k); Entry<K,V>[] tab = getTable();
*** 566,592 **** put(e.getKey(), e.getValue()); } /** * Removes the mapping for a key from this weak hash map if it is present. ! * More formally, if this map contains a mapping from key <tt>k</tt> to ! * value <tt>v</tt> such that <code>(key==null ? k==null : * key.equals(k))</code>, that mapping is removed. (The map can contain * at most one such mapping.) * * <p>Returns the value to which this map previously associated the key, ! * or <tt>null</tt> if the map contained no mapping for the key. A ! * return value of <tt>null</tt> does not <i>necessarily</i> indicate * that the map contained no mapping for the key; it's also possible ! * that the map explicitly mapped the key to <tt>null</tt>. * * <p>The map will not contain a mapping for the specified key once the * call returns. * * @param key key whose mapping is to be removed from the map ! * @return the previous value associated with <tt>key</tt>, or ! * <tt>null</tt> if there was no mapping for <tt>key</tt> */ public V remove(Object key) { Object k = maskNull(key); int h = hash(k); Entry<K,V>[] tab = getTable(); --- 566,592 ---- put(e.getKey(), e.getValue()); } /** * Removes the mapping for a key from this weak hash map if it is present. ! * More formally, if this map contains a mapping from key {@code k} to ! * value {@code v} such that <code>(key==null ? k==null : * key.equals(k))</code>, that mapping is removed. (The map can contain * at most one such mapping.) * * <p>Returns the value to which this map previously associated the key, ! * or {@code null} if the map contained no mapping for the key. A ! * return value of {@code null} does not <i>necessarily</i> indicate * that the map contained no mapping for the key; it's also possible ! * that the map explicitly mapped the key to {@code null}. * * <p>The map will not contain a mapping for the specified key once the * call returns. * * @param key key whose mapping is to be removed from the map ! * @return the previous value associated with {@code key}, or ! * {@code null} if there was no mapping for {@code key} */ public V remove(Object key) { Object k = maskNull(key); int h = hash(k); Entry<K,V>[] tab = getTable();
*** 662,676 **** while (queue.poll() != null) ; } /** ! * Returns <tt>true</tt> if this map maps one or more keys to the * specified value. * * @param value value whose presence in this map is to be tested ! * @return <tt>true</tt> if this map maps one or more keys to the * specified value */ public boolean containsValue(Object value) { if (value==null) return containsNullValue(); --- 662,676 ---- while (queue.poll() != null) ; } /** ! * Returns {@code true} if this map maps one or more keys to the * specified value. * * @param value value whose presence in this map is to be tested ! * @return {@code true} if this map maps one or more keys to the * specified value */ public boolean containsValue(Object value) { if (value==null) return containsNullValue();
*** 853,868 **** /** * Returns a {@link Set} view of the keys contained in this map. * The set is backed by the map, so changes to the map are * reflected in the set, and vice-versa. If the map is modified * while an iteration over the set is in progress (except through ! * the iterator's own <tt>remove</tt> operation), the results of * the iteration are undefined. The set supports element removal, * which removes the corresponding mapping from the map, via the ! * <tt>Iterator.remove</tt>, <tt>Set.remove</tt>, ! * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt> ! * operations. It does not support the <tt>add</tt> or <tt>addAll</tt> * operations. */ public Set<K> keySet() { Set<K> ks = keySet; return (ks != null ? ks : (keySet = new KeySet())); --- 853,868 ---- /** * Returns a {@link Set} view of the keys contained in this map. * The set is backed by the map, so changes to the map are * reflected in the set, and vice-versa. If the map is modified * while an iteration over the set is in progress (except through ! * the iterator's own {@code remove} operation), the results of * the iteration are undefined. The set supports element removal, * which removes the corresponding mapping from the map, via the ! * {@code Iterator.remove}, {@code Set.remove}, ! * {@code removeAll}, {@code retainAll}, and {@code clear} ! * operations. It does not support the {@code add} or {@code addAll} * operations. */ public Set<K> keySet() { Set<K> ks = keySet; return (ks != null ? ks : (keySet = new KeySet()));
*** 902,918 **** /** * Returns a {@link Collection} view of the values contained in this map. * The collection is backed by the map, so changes to the map are * reflected in the collection, and vice-versa. If the map is * modified while an iteration over the collection is in progress ! * (except through the iterator's own <tt>remove</tt> operation), * the results of the iteration are undefined. The collection * supports element removal, which removes the corresponding ! * mapping from the map, via the <tt>Iterator.remove</tt>, ! * <tt>Collection.remove</tt>, <tt>removeAll</tt>, ! * <tt>retainAll</tt> and <tt>clear</tt> operations. It does not ! * support the <tt>add</tt> or <tt>addAll</tt> operations. */ public Collection<V> values() { Collection<V> vs = values; return (vs != null) ? vs : (values = new Values()); } --- 902,918 ---- /** * Returns a {@link Collection} view of the values contained in this map. * The collection is backed by the map, so changes to the map are * reflected in the collection, and vice-versa. If the map is * modified while an iteration over the collection is in progress ! * (except through the iterator's own {@code remove} operation), * the results of the iteration are undefined. The collection * supports element removal, which removes the corresponding ! * mapping from the map, via the {@code Iterator.remove}, ! * {@code Collection.remove}, {@code removeAll}, ! * {@code retainAll} and {@code clear} operations. It does not ! * support the {@code add} or {@code addAll} operations. */ public Collection<V> values() { Collection<V> vs = values; return (vs != null) ? vs : (values = new Values()); }
*** 942,959 **** /** * Returns a {@link Set} view of the mappings contained in this map. * The set is backed by the map, so changes to the map are * reflected in the set, and vice-versa. If the map is modified * while an iteration over the set is in progress (except through ! * the iterator's own <tt>remove</tt> operation, or through the ! * <tt>setValue</tt> operation on a map entry returned by the * iterator) the results of the iteration are undefined. The set * supports element removal, which removes the corresponding ! * mapping from the map, via the <tt>Iterator.remove</tt>, ! * <tt>Set.remove</tt>, <tt>removeAll</tt>, <tt>retainAll</tt> and ! * <tt>clear</tt> operations. It does not support the ! * <tt>add</tt> or <tt>addAll</tt> operations. */ public Set<Map.Entry<K,V>> entrySet() { Set<Map.Entry<K,V>> es = entrySet; return es != null ? es : (entrySet = new EntrySet()); } --- 942,959 ---- /** * Returns a {@link Set} view of the mappings contained in this map. * The set is backed by the map, so changes to the map are * reflected in the set, and vice-versa. If the map is modified * while an iteration over the set is in progress (except through ! * the iterator's own {@code remove} operation, or through the ! * {@code setValue} operation on a map entry returned by the * iterator) the results of the iteration are undefined. The set * supports element removal, which removes the corresponding ! * mapping from the map, via the {@code Iterator.remove}, ! * {@code Set.remove}, {@code removeAll}, {@code retainAll} and ! * {@code clear} operations. It does not support the ! * {@code add} or {@code addAll} operations. */ public Set<Map.Entry<K,V>> entrySet() { Set<Map.Entry<K,V>> es = entrySet; return es != null ? es : (entrySet = new EntrySet()); }
< prev index next >