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 + -
显示快捷键?