| /* WeakHashMap -- a hashtable that keeps only weak references | |
| to its keys, allowing the virtual machine to reclaim them | |
| Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. | |
| This file is part of GNU Classpath. | |
| GNU Classpath is free software; you can redistribute it and/or modify | |
| it under the terms of the GNU General Public License as published by | |
| the Free Software Foundation; either version 2, or (at your option) | |
| any later version. | |
| GNU Classpath is distributed in the hope that it will be useful, but | |
| WITHOUT ANY WARRANTY; without even the implied warranty of | |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| General Public License for more details. | |
| You should have received a copy of the GNU General Public License | |
| along with GNU Classpath; see the file COPYING. If not, write to the | |
| Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | |
| 02110-1301 USA. | |
| Linking this library statically or dynamically with other modules is | |
| making a combined work based on this library. Thus, the terms and | |
| conditions of the GNU General Public License cover the whole | |
| combination. | |
| As a special exception, the copyright holders of this library give you | |
| permission to link this library with independent modules to produce an | |
| executable, regardless of the license terms of these independent | |
| modules, and to copy and distribute the resulting executable under | |
| terms of your choice, provided that you also meet, for each linked | |
| independent module, the terms and conditions of the license of that | |
| module. An independent module is a module which is not derived from | |
| or based on this library. If you modify this library, you may extend | |
| this exception to your version of the library, but you are not | |
| obligated to do so. If you do not wish to do so, delete this | |
| exception statement from your version. */ | |
| package java.util; | |
| import java.lang.ref.ReferenceQueue; | |
| import java.lang.ref.WeakReference; | |
| /** | |
| * A weak hash map has only weak references to the key. This means that it | |
| * allows the key to be garbage collected if it is not used otherwise. If | |
| * this happens, the entry will eventually disappear from the map, | |
| * asynchronously. | |
| * | |
| * <p>A weak hash map makes most sense when the keys doesn't override the | |
| * <code>equals</code> method: If there is no other reference to the | |
| * key nobody can ever look up the key in this table and so the entry | |
| * can be removed. This table also works when the <code>equals</code> | |
| * method is overloaded, such as String keys, but you should be prepared | |
| * to deal with some entries disappearing spontaneously. | |
| * | |
| * <p>Other strange behaviors to be aware of: The size of this map may | |
| * spontaneously shrink (even if you use a synchronized map and synchronize | |
| * it); it behaves as if another thread removes entries from this table | |
| * without synchronization. The entry set returned by <code>entrySet</code> | |
| * has similar phenomenons: The size may spontaneously shrink, or an | |
| * entry, that was in the set before, suddenly disappears. | |
| * | |
| * <p>A weak hash map is not meant for caches; use a normal map, with | |
| * soft references as values instead, or try {@link LinkedHashMap}. | |
| * | |
| * <p>The weak hash map supports null values and null keys. The null key | |
| * is never deleted from the map (except explictly of course). The | |
| * performance of the methods are similar to that of a hash map. | |
| * | |
| * <p>The value objects are strongly referenced by this table. So if a | |
| * value object maintains a strong reference to the key (either direct | |
| * or indirect) the key will never be removed from this map. According | |
| * to Sun, this problem may be fixed in a future release. It is not | |
| * possible to do it with the jdk 1.2 reference model, though. | |
| * | |
| * @author Jochen Hoenicke | |
| * @author Eric Blake (ebb9@email.byu.edu) | |
| * | |
| * @see HashMap | |
| * @see WeakReference | |
| * @see LinkedHashMap | |
| * @since 1.2 | |
| * @status updated to 1.4 | |
| */ | |
| public class WeakHashMap extends AbstractMap implements Map | |
| { | |
| // WARNING: WeakHashMap is a CORE class in the bootstrap cycle. See the | |
| // comments in vm/reference/java/lang/Runtime for implications of this fact. | |
| /** | |
| * The default capacity for an instance of HashMap. | |
| * Sun's documentation mildly suggests that this (11) is the correct | |
| * value. | |
| */ | |
| private static final int DEFAULT_CAPACITY = 11; | |
| /** | |
| * The default load factor of a HashMap. | |
| */ | |
| private static final float DEFAULT_LOAD_FACTOR = 0.75F; | |
| /** | |
| * This is used instead of the key value <i>null</i>. It is needed | |
| * to distinguish between an null key and a removed key. | |
| */ | |
| // Package visible for use by nested classes. | |
| static final Object NULL_KEY = new Object() | |
| { | |
| /** | |
| * Sets the hashCode to 0, since that's what null would map to. | |
| * @return the hash code 0 | |
| */ | |
| public int hashCode() | |
| { | |
| return 0; | |
| } | |
| /** | |
| * Compares this key to the given object. Normally, an object should | |
| * NEVER compare equal to null, but since we don't publicize NULL_VALUE, | |
| * it saves bytecode to do so here. | |
| * @return true iff o is this or null | |
| */ | |
| public boolean equals(Object o) | |
| { | |
| return null == o || this == o; | |
| } | |
| }; | |
| /** | |
| * The reference queue where our buckets (which are WeakReferences) are | |
| * registered to. | |
| */ | |
| private final ReferenceQueue queue; | |
| /** | |
| * The number of entries in this hash map. | |
| */ | |
| // Package visible for use by nested classes. | |
| int size; | |
| /** | |
| * The load factor of this WeakHashMap. This is the maximum ratio of | |
| * size versus number of buckets. If size grows the number of buckets | |
| * must grow, too. | |
| */ | |
| private float loadFactor; | |
| /** | |
| * The rounded product of the capacity (i.e. number of buckets) and | |
| * the load factor. When the number of elements exceeds the | |
| * threshold, the HashMap calls <code>rehash()</code>. | |
| */ | |
| private int threshold; | |
| /** | |
| * The number of structural modifications. This is used by | |
| * iterators, to see if they should fail. This doesn't count | |
| * the silent key removals, when a weak reference is cleared | |
| * by the garbage collection. Instead the iterators must make | |
| * sure to have strong references to the entries they rely on. | |
| */ | |
| // Package visible for use by nested classes. | |
| int modCount; | |
| /** | |
| * The entry set. There is only one instance per hashmap, namely | |
| * theEntrySet. Note that the entry set may silently shrink, just | |
| * like the WeakHashMap. | |
| */ | |
| private final class WeakEntrySet extends AbstractSet | |
| { | |
| /** | |
| * Non-private constructor to reduce bytecode emitted. | |
| */ | |
| WeakEntrySet() | |
| { | |
| } | |
| /** | |
| * Returns the size of this set. | |
| * | |
| * @return the set size | |
| */ | |
| public int size() | |
| { | |
| return size; | |
| } | |
| /** | |
| * Returns an iterator for all entries. | |
| * | |
| * @return an Entry iterator | |
| */ | |
| public Iterator iterator() | |
| { | |
| return new Iterator() | |
| { | |
| /** | |
| * The entry that was returned by the last | |
| * <code>next()</code> call. This is also the entry whose | |
| * bucket should be removed by the <code>remove</code> call. <br> | |
| * | |
| * It is null, if the <code>next</code> method wasn't | |
| * called yet, or if the entry was already removed. <br> | |
| * | |
| * Remembering this entry here will also prevent it from | |
| * being removed under us, since the entry strongly refers | |
| * to the key. | |
| */ | |
| WeakBucket.WeakEntry lastEntry; | |
| /** | |
| * The entry that will be returned by the next | |
| * <code>next()</code> call. It is <code>null</code> if there | |
| * is no further entry. <br> | |
| * | |
| * Remembering this entry here will also prevent it from | |
| * being removed under us, since the entry strongly refers | |
| * to the key. | |
| */ | |
| WeakBucket.WeakEntry nextEntry = findNext(null); | |
| /** | |
| * The known number of modification to the list, if it differs | |
| * from the real number, we throw an exception. | |
| */ | |
| int knownMod = modCount; | |
| /** | |
| * Check the known number of modification to the number of | |
| * modifications of the table. If it differs from the real | |
| * number, we throw an exception. | |
| * @throws ConcurrentModificationException if the number | |
| * of modifications doesn't match. | |
| */ | |
| private void checkMod() | |
| { | |
| // This method will get inlined. | |
| cleanQueue(); | |
| if (knownMod != modCount) | |
| throw new ConcurrentModificationException(knownMod + " != " | |
| + modCount); | |
| } | |
| /** | |
| * Get a strong reference to the next entry after | |
| * lastBucket. | |
| * @param lastEntry the previous bucket, or null if we should | |
| * get the first entry. | |
| * @return the next entry. | |
| */ | |
| private WeakBucket.WeakEntry findNext(WeakBucket.WeakEntry lastEntry) | |
| { | |
| int slot; | |
| WeakBucket nextBucket; | |
| if (lastEntry != null) | |
| { | |
| nextBucket = lastEntry.getBucket().next; | |
| slot = lastEntry.getBucket().slot; | |
| } | |
| else | |
| { | |
| nextBucket = buckets[0]; | |
| slot = 0; | |
| } | |
| while (true) | |
| { | |
| while (nextBucket != null) | |
| { | |
| WeakBucket.WeakEntry entry = nextBucket.getEntry(); | |
| if (entry != null) | |
| // This is the next entry. | |
| return entry; | |
| // Entry was cleared, try next. | |
| nextBucket = nextBucket.next; | |
| } | |
| slot++; | |
| if (slot == buckets.length) | |
| // No more buckets, we are through. | |
| return null; | |
| nextBucket = buckets[slot]; | |
| } | |
| } | |
| /** | |
| * Checks if there are more entries. | |
| * @return true, iff there are more elements. | |
| */ | |
| public boolean hasNext() | |
| { | |
| return nextEntry != null; | |
| } | |
| /** | |
| * Returns the next entry. | |
| * @return the next entry. | |
| * @throws ConcurrentModificationException if the hash map was | |
| * modified. | |
| * @throws NoSuchElementException if there is no entry. | |
| */ | |
| public Object next() | |
| { | |
| checkMod(); | |
| if (nextEntry == null) | |
| throw new NoSuchElementException(); | |
| lastEntry = nextEntry; | |
| nextEntry = findNext(lastEntry); | |
| return lastEntry; | |
| } | |
| /** | |
| * Removes the last returned entry from this set. This will | |
| * also remove the bucket of the underlying weak hash map. | |
| * @throws ConcurrentModificationException if the hash map was | |
| * modified. | |
| * @throws IllegalStateException if <code>next()</code> was | |
| * never called or the element was already removed. | |
| */ | |
| public void remove() | |
| { | |
| checkMod(); | |
| if (lastEntry == null) | |
| throw new IllegalStateException(); | |
| modCount++; | |
| internalRemove(lastEntry.getBucket()); | |
| lastEntry = null; | |
| knownMod++; | |
| } | |
| }; | |
| } | |
| } | |
| /** | |
| * A bucket is a weak reference to the key, that contains a strong | |
| * reference to the value, a pointer to the next bucket and its slot | |
| * number. <br> | |
| * | |
| * It would be cleaner to have a WeakReference as field, instead of | |
| * extending it, but if a weak reference gets cleared, we only get | |
| * the weak reference (by queue.poll) and wouldn't know where to | |
| * look for this reference in the hashtable, to remove that entry. | |
| * | |
| * @author Jochen Hoenicke | |
| */ | |
| private static class WeakBucket extends WeakReference | |
| { | |
| /** | |
| * The value of this entry. The key is stored in the weak | |
| * reference that we extend. | |
| */ | |
| Object value; | |
| /** | |
| * The next bucket describing another entry that uses the same | |
| * slot. | |
| */ | |
| WeakBucket next; | |
| /** | |
| * The slot of this entry. This should be | |
| * <code>Math.abs(key.hashCode() % buckets.length)</code>. | |
| * | |
| * But since the key may be silently removed we have to remember | |
| * the slot number. | |
| * | |
| * If this bucket was removed the slot is -1. This marker will | |
| * prevent the bucket from being removed twice. | |
| */ | |
| int slot; | |
| /** | |
| * Creates a new bucket for the given key/value pair and the specified | |
| * slot. | |
| * @param key the key | |
| * @param queue the queue the weak reference belongs to | |
| * @param value the value | |
| * @param slot the slot. This must match the slot where this bucket | |
| * will be enqueued. | |
| */ | |
| public WeakBucket(Object key, ReferenceQueue queue, Object value, | |
| int slot) | |
| { | |
| super(key, queue); | |
| this.value = value; | |
| this.slot = slot; | |
| } | |
| /** | |
| * This class gives the <code>Entry</code> representation of the | |
| * current bucket. It also keeps a strong reference to the | |
| * key; bad things may happen otherwise. | |
| */ | |
| class WeakEntry implements Map.Entry | |
| { | |
| /** | |
| * The strong ref to the key. | |
| */ | |
| Object key; | |
| /** | |
| * Creates a new entry for the key. | |
| * @param key the key | |
| */ | |
| public WeakEntry(Object key) | |
| { | |
| this.key = key; | |
| } | |
| /** | |
| * Returns the underlying bucket. | |
| * @return the owning bucket | |
| */ | |
| public WeakBucket getBucket() | |
| { | |
| return WeakBucket.this; | |
| } | |
| /** | |
| * Returns the key. | |
| * @return the key | |
| */ | |
| public Object getKey() | |
| { | |
| return key == NULL_KEY ? null : key; | |
| } | |
| /** | |
| * Returns the value. | |
| * @return the value | |
| */ | |
| public Object getValue() | |
| { | |
| return value; | |
| } | |
| /** | |
| * This changes the value. This change takes place in | |
| * the underlying hash map. | |
| * @param newVal the new value | |
| * @return the old value | |
| */ | |
| public Object setValue(Object newVal) | |
| { | |
| Object oldVal = value; | |
| value = newVal; | |
| return oldVal; | |
| } | |
| /** | |
| * The hashCode as specified in the Entry interface. | |
| * @return the hash code | |
| */ | |
| public int hashCode() | |
| { | |
| return key.hashCode() ^ WeakHashMap.hashCode(value); | |
| } | |
| /** | |
| * The equals method as specified in the Entry interface. | |
| * @param o the object to compare to | |
| * @return true iff o represents the same key/value pair | |
| */ | |
| public boolean equals(Object o) | |
| { | |
| if (o instanceof Map.Entry) | |
| { | |
| Map.Entry e = (Map.Entry) o; | |
| return WeakHashMap.equals(getKey(), e.getKey()) | |
| && WeakHashMap.equals(value, e.getValue()); | |
| } | |
| return false; | |
| } | |
| public String toString() | |
| { | |
| return getKey() + "=" + value; | |
| } | |
| } | |
| /** | |
| * This returns the entry stored in this bucket, or null, if the | |
| * bucket got cleared in the mean time. | |
| * @return the Entry for this bucket, if it exists | |
| */ | |
| WeakEntry getEntry() | |
| { | |
| final Object key = this.get(); | |
| if (key == null) | |
| return null; | |
| return new WeakEntry(key); | |
| } | |
| } | |
| /** | |
| * The entry set returned by <code>entrySet()</code>. | |
| */ | |
| private final WeakEntrySet theEntrySet; | |
| /** | |
| * The hash buckets. These are linked lists. Package visible for use in | |
| * nested classes. | |
| */ | |
| WeakBucket[] buckets; | |
| /** | |
| * Creates a new weak hash map with default load factor and default | |
| * capacity. | |
| */ | |
| public WeakHashMap() | |
| { | |
| this(DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR); | |
| } | |
| /** | |
| * Creates a new weak hash map with default load factor and the given | |
| * capacity. | |
| * @param initialCapacity the initial capacity | |
| * @throws IllegalArgumentException if initialCapacity is negative | |
| */ | |
| public WeakHashMap(int initialCapacity) | |
| { | |
| this(initialCapacity, DEFAULT_LOAD_FACTOR); | |
| } | |
| /** | |
| * Creates a new weak hash map with the given initial capacity and | |
| * load factor. | |
| * @param initialCapacity the initial capacity. | |
| * @param loadFactor the load factor (see class description of HashMap). | |
| * @throws IllegalArgumentException if initialCapacity is negative, or | |
| * loadFactor is non-positive | |
| */ | |
| public WeakHashMap(int initialCapacity, float loadFactor) | |
| { | |
| // Check loadFactor for NaN as well. | |
| if (initialCapacity < 0 || ! (loadFactor > 0)) | |
| throw new IllegalArgumentException(); | |
| if (initialCapacity == 0) | |
| initialCapacity = 1; | |
| this.loadFactor = loadFactor; | |
| threshold = (int) (initialCapacity * loadFactor); | |
| theEntrySet = new WeakEntrySet(); | |
| queue = new ReferenceQueue(); | |
| buckets = new WeakBucket[initialCapacity]; | |
| } | |
| /** | |
| * Construct a new WeakHashMap with the same mappings as the given map. | |
| * The WeakHashMap has a default load factor of 0.75. | |
| * | |
| * @param m the map to copy | |
| * @throws NullPointerException if m is null | |
| * @since 1.3 | |
| */ | |
| public WeakHashMap(Map m) | |
| { | |
| this(m.size(), DEFAULT_LOAD_FACTOR); | |
| putAll(m); | |
| } | |
| /** | |
| * Simply hashes a non-null Object to its array index. | |
| * @param key the key to hash | |
| * @return its slot number | |
| */ | |
| private int hash(Object key) | |
| { | |
| return Math.abs(key.hashCode() % buckets.length); | |
| } | |
| /** | |
| * Cleans the reference queue. This will poll all references (which | |
| * are WeakBuckets) from the queue and remove them from this map. | |
| * This will not change modCount, even if it modifies the map. The | |
| * iterators have to make sure that nothing bad happens. <br> | |
| * | |
| * Currently the iterator maintains a strong reference to the key, so | |
| * that is no problem. | |
| */ | |
| // Package visible for use by nested classes. | |
| void cleanQueue() | |
| { | |
| Object bucket = queue.poll(); | |
| while (bucket != null) | |
| { | |
| internalRemove((WeakBucket) bucket); | |
| bucket = queue.poll(); | |
| } | |
| } | |
| /** | |
| * Rehashes this hashtable. This will be called by the | |
| * <code>add()</code> method if the size grows beyond the threshold. | |
| * It will grow the bucket size at least by factor two and allocates | |
| * new buckets. | |
| */ | |
| private void rehash() | |
| { | |
| WeakBucket[] oldBuckets = buckets; | |
| int newsize = buckets.length * 2 + 1; // XXX should be prime. | |
| threshold = (int) (newsize * loadFactor); | |
| buckets = new WeakBucket[newsize]; | |
| // Now we have to insert the buckets again. | |
| for (int i = 0; i < oldBuckets.length; i++) | |
| { | |
| WeakBucket bucket = oldBuckets[i]; | |
| WeakBucket nextBucket; | |
| while (bucket != null) | |
| { | |
| nextBucket = bucket.next; | |
| Object key = bucket.get(); | |
| if (key == null) | |
| { | |
| // This bucket should be removed; it is probably | |
| // already on the reference queue. We don't insert it | |
| // at all, and mark it as cleared. | |
| bucket.slot = -1; | |
| size--; | |
| } | |
| else | |
| { | |
| // Add this bucket to its new slot. | |
| int slot = hash(key); | |
| bucket.slot = slot; | |
| bucket.next = buckets[slot]; | |
| buckets[slot] = bucket; | |
| } | |
| bucket = nextBucket; | |
| } | |
| } | |
| } | |
| /** | |
| * Finds the entry corresponding to key. Since it returns an Entry | |
| * it will also prevent the key from being removed under us. | |
| * @param key the key, may be null | |
| * @return The WeakBucket.WeakEntry or null, if the key wasn't found. | |
| */ | |
| private WeakBucket.WeakEntry internalGet(Object key) | |
| { | |
| if (key == null) | |
| key = NULL_KEY; | |
| int slot = hash(key); | |
| WeakBucket bucket = buckets[slot]; | |
| while (bucket != null) | |
| { | |
| WeakBucket.WeakEntry entry = bucket.getEntry(); | |
| if (entry != null && equals(key, entry.key)) | |
| return entry; | |
| bucket = bucket.next; | |
| } | |
| return null; | |
| } | |
| /** | |
| * Adds a new key/value pair to the hash map. | |
| * @param key the key. This mustn't exists in the map. It may be null. | |
| * @param value the value. | |
| */ | |
| private void internalAdd(Object key, Object value) | |
| { | |
| if (key == null) | |
| key = NULL_KEY; | |
| int slot = hash(key); | |
| WeakBucket bucket = new WeakBucket(key, queue, value, slot); | |
| bucket.next = buckets[slot]; | |
| buckets[slot] = bucket; | |
| size++; | |
| } | |
| /** | |
| * Removes a bucket from this hash map, if it wasn't removed before | |
| * (e.g. one time through rehashing and one time through reference queue). | |
| * Package visible for use in nested classes. | |
| * | |
| * @param bucket the bucket to remove. | |
| */ | |
| void internalRemove(WeakBucket bucket) | |
| { | |
| int slot = bucket.slot; | |
| if (slot == -1) | |
| // This bucket was already removed. | |
| return; | |
| // Mark the bucket as removed. This is necessary, since the | |
| // bucket may be enqueued later by the garbage collection, and | |
| // internalRemove will be called a second time. | |
| bucket.slot = -1; | |
| WeakBucket prev = null; | |
| WeakBucket next = buckets[slot]; | |
| while (next != bucket) | |
| { | |
| if (next == null) throw new InternalError("WeakHashMap in incosistent state"); | |
| prev = next; | |
| next = prev.next; | |
| } | |
| if (prev == null) | |
| buckets[slot] = bucket.next; | |
| else | |
| prev.next = bucket.next; | |
| size--; | |
| } | |
| /** | |
| * Returns the size of this hash map. Note that the size() may shrink | |
| * spontaneously, if the some of the keys were only weakly reachable. | |
| * @return the number of entries in this hash map. | |
| */ | |
| public int size() | |
| { | |
| cleanQueue(); | |
| return size; | |
| } | |
| /** | |
| * Tells if the map is empty. Note that the result may change | |
| * spontanously, if all of the keys were only weakly reachable. | |
| * @return true, iff the map is empty. | |
| */ | |
| public boolean isEmpty() | |
| { | |
| cleanQueue(); | |
| return size == 0; | |
| } | |
| /** | |
| * Tells if the map contains the given key. Note that the result | |
| * may change spontanously, if the key was only weakly | |
| * reachable. | |
| * @param key the key to look for | |
| * @return true, iff the map contains an entry for the given key. | |
| */ | |
| public boolean containsKey(Object key) | |
| { | |
| cleanQueue(); | |
| return internalGet(key) != null; | |
| } | |
| /** | |
| * Gets the value the key is mapped to. | |
| * @return the value the key was mapped to. It returns null if | |
| * the key wasn't in this map, or if the mapped value was | |
| * explicitly set to null. | |
| */ | |
| public Object get(Object key) | |
| { | |
| cleanQueue(); | |
| WeakBucket.WeakEntry entry = internalGet(key); | |
| return entry == null ? null : entry.getValue(); | |
| } | |
| /** | |
| * Adds a new key/value mapping to this map. | |
| * @param key the key, may be null | |
| * @param value the value, may be null | |
| * @return the value the key was mapped to previously. It returns | |
| * null if the key wasn't in this map, or if the mapped value | |
| * was explicitly set to null. | |
| */ | |
| public Object put(Object key, Object value) | |
| { | |
| cleanQueue(); | |
| WeakBucket.WeakEntry entry = internalGet(key); | |
| if (entry != null) | |
| return entry.setValue(value); | |
| modCount++; | |
| if (size >= threshold) | |
| rehash(); | |
| internalAdd(key, value); | |
| return null; | |
| } | |
| /** | |
| * Removes the key and the corresponding value from this map. | |
| * @param key the key. This may be null. | |
| * @return the value the key was mapped to previously. It returns | |
| * null if the key wasn't in this map, or if the mapped value was | |
| * explicitly set to null. | |
| */ | |
| public Object remove(Object key) | |
| { | |
| cleanQueue(); | |
| WeakBucket.WeakEntry entry = internalGet(key); | |
| if (entry == null) | |
| return null; | |
| modCount++; | |
| internalRemove(entry.getBucket()); | |
| return entry.getValue(); | |
| } | |
| /** | |
| * Returns a set representation of the entries in this map. This | |
| * set will not have strong references to the keys, so they can be | |
| * silently removed. The returned set has therefore the same | |
| * strange behaviour (shrinking size(), disappearing entries) as | |
| * this weak hash map. | |
| * @return a set representation of the entries. | |
| */ | |
| public Set entrySet() | |
| { | |
| cleanQueue(); | |
| return theEntrySet; | |
| } | |
| /** | |
| * Clears all entries from this map. | |
| */ | |
| public void clear() | |
| { | |
| super.clear(); | |
| } | |
| /** | |
| * Returns true if the map contains at least one key which points to | |
| * the specified object as a value. Note that the result | |
| * may change spontanously, if its key was only weakly reachable. | |
| * @param value the value to search for | |
| * @return true if it is found in the set. | |
| */ | |
| public boolean containsValue(Object value) | |
| { | |
| cleanQueue(); | |
| return super.containsValue(value); | |
| } | |
| /** | |
| * Returns a set representation of the keys in this map. This | |
| * set will not have strong references to the keys, so they can be | |
| * silently removed. The returned set has therefore the same | |
| * strange behaviour (shrinking size(), disappearing entries) as | |
| * this weak hash map. | |
| * @return a set representation of the keys. | |
| */ | |
| public Set keySet() | |
| { | |
| cleanQueue(); | |
| return super.keySet(); | |
| } | |
| /** | |
| * Puts all of the mappings from the given map into this one. If the | |
| * key already exists in this map, its value is replaced. | |
| * @param m the map to copy in | |
| */ | |
| public void putAll(Map m) | |
| { | |
| super.putAll(m); | |
| } | |
| /** | |
| * Returns a collection representation of the values in this map. This | |
| * collection will not have strong references to the keys, so mappings | |
| * can be silently removed. The returned collection has therefore the same | |
| * strange behaviour (shrinking size(), disappearing entries) as | |
| * this weak hash map. | |
| * @return a collection representation of the values. | |
| */ | |
| public Collection values() | |
| { | |
| cleanQueue(); | |
| return super.values(); | |
| } | |
| } // class WeakHashMap |