identityweakhashmap.java

来自「This is a resource based on j2me embedde」· Java 代码 · 共 967 行 · 第 1/3 页

JAVA
967
字号
/* * @(#)IdentityWeakHashMap.java	1.20 06/10/10 * * Copyright  1990-2008 Sun Microsystems, Inc. All Rights Reserved.   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER   *    * This program is free software; you can redistribute it and/or   * modify it under the terms of the GNU General Public License version   * 2 only, as published by the Free Software Foundation.    *    * This program 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 version 2 for more details (a copy is   * included at /legal/license.txt).    *    * You should have received a copy of the GNU General Public License   * version 2 along with this work; if not, write to the Free Software   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA   * 02110-1301 USA    *    * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa   * Clara, CA 95054 or visit www.sun.com if you need additional   * information or have any questions.  * */package sun.awt;import java.lang.ref.WeakReference;import java.lang.ref.ReferenceQueue;import java.util.AbstractCollection;import java.util.AbstractMap;import java.util.AbstractSet;import java.util.ArrayList;import java.util.Collection;import java.util.ConcurrentModificationException;import java.util.Iterator;import java.util.Map;import java.util.NoSuchElementException;import java.util.Set;class IdentityWeakHashMap 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>IdentityWeakHashMap</tt> with the given initial     * capacity and the given load factor.     *     * @param  initialCapacity The initial capacity of the <tt>IdentityWeakHashMap</tt>     * @param  loadFactor      The load factor of the <tt>IdentityWeakHashMap</tt>     * @throws IllegalArgumentException  If the initial capacity is negative,     *         or if the load factor is nonpositive.     */    public IdentityWeakHashMap(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>IdentityWeakHashMap</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>IdentityWeakHashMap</tt>     * @throws IllegalArgumentException  If the initial capacity is negative.     */    public IdentityWeakHashMap(int initialCapacity) {        this(initialCapacity, DEFAULT_LOAD_FACTOR);    }    /**     * Constructs a new, empty <tt>IdentityWeakHashMap</tt> with the default initial     * capacity (16) and the default load factor (0.75).     */    public IdentityWeakHashMap() {        this.loadFactor = DEFAULT_LOAD_FACTOR;        threshold = (int)(DEFAULT_INITIAL_CAPACITY);        table = new Entry[DEFAULT_INITIAL_CAPACITY];    }      /**     * Constructs a new <tt>IdentityWeakHashMap</tt> with the same mappings as the     * specified <tt>Map</tt>.  The <tt>IdentityWeakHashMap</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 IdentityWeakHashMap(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;    }    /**     * 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.     */    public boolean isEmpty() {        return size() == 0;    }    /**     * Returns the value to which the specified key is mapped in this weak     * hash map, or <tt>null</tt> if the map contains no mapping for     * this key.  A return value of <tt>null</tt> does not <i>necessarily</i>     * indicate that the map contains no mapping for the key; it is also     * possible that the map explicitly maps the key to <tt>null</tt>. The     * <tt>containsKey</tt> method may be used to distinguish these two     * cases.     *     * @param   key the key whose associated value is to be returned.     * @return  the value to which this map maps the specified key, or     *          <tt>null</tt> if the map contains no mapping for this key.     * @see #put(Object, Object)     */    public Object get(Object key) {        Object k = maskNull(key);        int h = hash(k);        Entry[] tab = getTable();        int index = indexFor(h, tab.length);        Entry e = tab[index];         while (e != null) {            if (e.hash == h && eq(k, e.get()))                return e.value;            e = e.next;        }        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;    }    /**     * Returns the entry associated with the specified key in the HashMap.     * Returns null if the HashMap contains no mapping for this key.     */    Entry getEntry(Object key) {        Object k = maskNull(key);        int h = hash(k);        Entry[] tab = getTable();        int index = indexFor(h, tab.length);        Entry e = tab[index];         while (e != null && !(e.hash == h && eq(k, e.get())))            e = e.next;        return e;    }    /**     * Associates the specified value with the specified key in this map.     * 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 previous value associated with specified key, or <tt>null</tt>     *	       if there was no mapping for key.  A <tt>null</tt> return can     *	       also indicate that the HashMap previously associated     *	       <tt>null</tt> with the specified key.     */

⌨️ 快捷键说明

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