⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 weakhashmap.java

📁 java源代码 请看看啊 提点宝贵的意见
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
/* * @(#)WeakHashMap.java	1.24 03/01/23 * * Copyright 2003 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */package java.util;import java.lang.ref.WeakReference;import java.lang.ref.ReferenceQueue;/** * A hashtable-based <tt>Map</tt> implementation 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 than 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 * <tt>Collections.synchronizedMap</tt> 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 set, 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.  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 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> or <tt>add</tt> methods, the iterator will throw a * <tt>ConcurrentModificationException</tt>.  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  * <a href="{@docRoot}/../guide/collections/index.html"> * Java Collections Framework</a>. * * @version	1.24, 01/23/03 * @author      Doug Lea * @author      Josh Bloch * @author	Mark Reinhold * @since	1.2 * @see		java.util.HashMap * @see		java.lang.ref.WeakReference */public class WeakHashMap extends AbstractMap implements Map {    /**     * The default initial capacity -- MUST be a power of two.     */    private static final int DEFAULT_INITIAL_CAPACITY = 16;    /**     * The maximum capacity, used if a higher value is implicitly specified     * by either of the constructors with arguments.     * MUST be a power of two <= 1<<30.     */    private static final int MAXIMUM_CAPACITY = 1 << 30;    /**     * The load fast used when none specified in constructor.     */    private static final float DEFAULT_LOAD_FACTOR = 0.75f;    /**     * The table, resized as necessary. Length MUST Always be a power of two.     */    private Entry[] table;    /**     * The number of key-value mappings contained in this weak hash map.     */    private int size;      /**     * The next size value at which to resize (capacity * load factor).     */    private int threshold;      /**     * The load factor for the hash table.     */    private final float loadFactor;    /**     * Reference queue for cleared WeakEntries     */    private final ReferenceQueue queue = new ReferenceQueue();    /**     * The number of times this HashMap has been structurally modified     * Structural modifications are those that change the number of mappings in     * the HashMap or otherwise modify its internal structure (e.g.,     * rehash).  This field is used to make iterators on Collection-views of     * the HashMap fail-fast.  (See ConcurrentModificationException).     */    private volatile int modCount;    /**     * 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)            throw new IllegalArgumentException("Illegal Initial Capacity: "+                                               initialCapacity);        if (initialCapacity > MAXIMUM_CAPACITY)            initialCapacity = MAXIMUM_CAPACITY;        if (loadFactor <= 0 || Float.isNaN(loadFactor))            throw new IllegalArgumentException("Illegal Load factor: "+                                               loadFactor);        int capacity = 1;        while (capacity < initialCapacity)             capacity <<= 1;        table = new Entry[capacity];        this.loadFactor = loadFactor;        threshold = (int)(capacity * loadFactor);    }    /**     * Constructs a new, empty <tt>WeakHashMap</tt> with the given initial     * capacity and the default load factor, which is <tt>0.75</tt>.     *     * @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 the default load factor (0.75).     */    public WeakHashMap() {        this.loadFactor = DEFAULT_LOAD_FACTOR;        threshold = (int)(DEFAULT_INITIAL_CAPACITY);        table = new Entry[DEFAULT_INITIAL_CAPACITY];    }      /**     * Constructs a new <tt>WeakHashMap</tt> with the same mappings as the     * specified <tt>Map</tt>.  The <tt>WeakHashMap</tt> is created with      * default load factor, which is <tt>0.75</tt> and an initial capacity     * sufficient to hold the mappings in the specified <tt>Map</tt>.     *     * @param   t the map whose mappings are to be placed in this map.     * @throws  NullPointerException if the specified map is null.     * @since	1.3     */    public WeakHashMap(Map t) {        this(Math.max((int) (t.size() / DEFAULT_LOAD_FACTOR) + 1, 16),             DEFAULT_LOAD_FACTOR);        putAll(t);    }    // internal utilities    /**     * Value representing null keys inside tables.     */    private static final Object NULL_KEY = new Object();    /**     * Use NULL_KEY for key if it is null.     */    private static Object maskNull(Object key) {        return (key == null ? NULL_KEY : key);    }    /**     * Return internal representation of null key back to caller as null     */    private static Object unmaskNull(Object key) {        return (key == NULL_KEY ? null : key);    }    /**     * Check for equality of non-null reference x and possibly-null y.  By     * default uses Object.equals.     */    static boolean eq(Object x, Object y) {        return x == y || x.equals(y);    }    /**     * Return index for hash code h.      */    static int indexFor(int h, int length) {        return h & (length-1);    }    /**     * Expunge stale entries from the table.     */    private void expungeStaleEntries() {        Object r;        while ( (r = queue.poll()) != null) {            Entry e = (Entry)r;            int h = e.hash;            int i = indexFor(h, table.length);            Entry prev = table[i];            Entry p = prev;            while (p != null) {                Entry next = p.next;                if (p == e) {                    if (prev == e)                        table[i] = next;                    else                        prev.next = next;                    e.next = null;  // Help GC                    e.value = null; //  "   "                    size--;                    break;                }                prev = p;                p = next;            }        }    }    /**     * Return the table after first expunging stale entries     */    private Entry[] getTable() {        expungeStaleEntries();        return table;    }     /**     * Returns the number of key-value mappings in this map.     * 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 int size() {        if (size == 0)            return 0;        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.     */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -