identityweakhashmap.java

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

JAVA
967
字号
    public Object put(Object key, Object value) {        Object k = maskNull(key);        int h = hash(k);        Entry[] tab = getTable();        int i = indexFor(h, tab.length);        for (Entry e = tab[i]; e != null; e = e.next) {            if (h == e.hash && eq(k, e.get())) {                Object oldValue = e.value;                if (value != oldValue)                    e.value = value;                return oldValue;            }        }        modCount++;        tab[i] = new Entry(k, value, queue, h, tab[i]);        if (++size >= threshold)             resize(tab.length * 2);        return null;    }      /**     * Rehashes the contents of this map into a new array with a     * larger capacity.  This method is called automatically when the     * number of keys in this map reaches its threshold.     *     * If current capacity is MAXIMUM_CAPACITY, this method does not     * resize the map, but but sets threshold to Integer.MAX_VALUE.     * This has the effect of preventing future calls.     *     * @param newCapacity the new capacity, MUST be a power of two;     *        must be greater than current capacity unless current     *        capacity is MAXIMUM_CAPACITY (in which case value     *        is irrelevant).     */    void resize(int newCapacity) {        Entry[] oldTable = getTable();        int oldCapacity = oldTable.length;        if (oldCapacity == MAXIMUM_CAPACITY) {            threshold = Integer.MAX_VALUE;            return;        }        Entry[] newTable = new Entry[newCapacity];        transfer(oldTable, newTable);        table = newTable;        /*         * If ignoring null elements and processing ref queue caused massive         * shrinkage, then restore old table.  This should be rare, but avoids         * unbounded expansion of garbage-filled tables.         */        if (size >= threshold / 2) {            threshold = (int)(newCapacity * loadFactor);        } else {            expungeStaleEntries();            transfer(newTable, oldTable);            table = oldTable;        }    }    /** Transfer all entries from src to dest tables */    private void transfer(Entry[] src, Entry[] dest) {        for (int j = 0; j < src.length; ++j) {            Entry e = src[j];            src[j] = null;            while (e != null) {                Entry next = e.next;                Object key = e.get();                if (key == null) {                    e.next = null;  // Help GC                    e.value = null; //  "   "                    size--;                } else {                    int i = indexFor(e.hash, dest.length);                      e.next = dest[i];                    dest[i] = e;                }                e = next;            }        }    }    /**     * Copies all of the mappings from the specified map to this map These     * mappings will replace any mappings that this map had for any of the     * keys currently in the specified map.<p>     *     * @param m mappings to be stored in this map.     * @throws  NullPointerException if the specified map is null.     */    public void putAll(Map m) {        int numKeysToBeAdded = m.size();        if (numKeysToBeAdded == 0)            return;        /*         * Expand the map if the map if the number of mappings to be added         * is greater than or equal to threshold.  This is conservative; the         * obvious condition is (m.size() + size) >= threshold, but this         * condition could result in a map with twice the appropriate capacity,         * if the keys to be added overlap with the keys already in this map.         * By using the conservative calculation, we subject ourself         * to at most one extra resize.         */        if (numKeysToBeAdded > threshold) {            int targetCapacity = (int)(numKeysToBeAdded / loadFactor + 1);            if (targetCapacity > MAXIMUM_CAPACITY)                targetCapacity = MAXIMUM_CAPACITY;            int newCapacity = table.length;            while (newCapacity < targetCapacity)                newCapacity <<= 1;            if (newCapacity > table.length)                resize(newCapacity);        }        for (Iterator i = m.entrySet().iterator(); i.hasNext(); ) {            Map.Entry e = (Map.Entry) i.next();            put(e.getKey(), e.getValue());        }    }      /**     * Removes the mapping for this key from this map if present.     *     * @param key key whose mapping is to be removed from the map.     * @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 map previously associated <tt>null</tt>     *	       with the specified key.     */    public Object remove(Object key) {        Object k = maskNull(key);        int h = hash(k);        Entry[] tab = getTable();        int i = indexFor(h, tab.length);        Entry prev = tab[i];        Entry e = prev;        while (e != null) {            Entry next = e.next;            if (h == e.hash && eq(k, e.get())) {                modCount++;                size--;                if (prev == e)                     tab[i] = next;                else                    prev.next = next;                return e.value;            }            prev = e;            e = next;        }        return null;    }    /** Special version of remove needed by Entry set */    Entry removeMapping(Object o) {        if (!(o instanceof Map.Entry))            return null;        Entry[] tab = getTable();        Map.Entry entry = (Map.Entry)o;        Object k = maskNull(entry.getKey());        int h = hash(k);        int i = indexFor(h, tab.length);        Entry prev = tab[i];        Entry e = prev;        while (e != null) {            Entry next = e.next;            if (h == e.hash && e.equals(entry)) {                modCount++;                size--;                if (prev == e)                     tab[i] = next;                else                    prev.next = next;                return e;            }            prev = e;            e = next;        }           return null;    }    /**     * Removes all mappings from this map.     */    public void clear() {        // clear out ref queue. We don't need to expunge entries        // since table is getting cleared.        while (queue.poll() != null)            ;        modCount++;        Entry tab[] = table;        for (int i = 0; i < tab.length; ++i)             tab[i] = null;        size = 0;        // Allocation of array may have caused GC, which may have caused        // additional entries to go stale.  Removing these entries from the        // reference queue will make them eligible for reclamation.        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();	Entry tab[] = getTable();        for (int i = tab.length ; i-- > 0 ;)            for (Entry e = tab[i] ; e != null ; e = e.next)                if (value == e.value)                    return true;	return false;    }    /**     * Special-case code for containsValue with null argument     */    private boolean containsNullValue() {	Entry tab[] = getTable();        for (int i = tab.length ; i-- > 0 ;)            for (Entry e = tab[i] ; e != null ; e = e.next)                if (e.value==null)                    return true;	return false;    }    /**     * Returns a hash value for the specified object.  In addition to      * the object's own hashCode, this method applies a "supplemental     * hash function," which defends against poor quality hash functions.     * This is critical because HashMap uses power-of two length     * hash tables.<p>     *     * The shift distances in this function were chosen as the result     * of an automated search over the entire four-dimensional search space.     */    static int hash(Object x) {        int h = x.hashCode();          h += ~(h << 9);        h ^=  (h >>> 14);        h +=  (h << 4);        h ^=  (h >>> 10);        return h;    }    /**     * The entries in this hash table extend WeakReference, using its main ref     * field as the key.      */     private static class Entry extends WeakReference implements Map.Entry {        private Object value;        private final int hash;        private Entry next;        /**         * Create new entry.         */        Entry(Object key, Object value, ReferenceQueue queue,              int hash, Entry next) {             super(key, queue);             this.value = value;            this.hash  = hash;            this.next  = next;        }        public Object getKey() {            return unmaskNull(get());        }        public Object getValue() {            return value;        }            public Object setValue(Object newValue) {            Object oldValue = value;            value = newValue;            return oldValue;        }            public boolean equals(Object o) {            if (!(o instanceof Map.Entry))                return false;            Map.Entry e = (Map.Entry)o;            Object k1 = getKey();            Object k2 = e.getKey();            if (k1 == k2) {                 Object v1 = getValue();                Object v2 = e.getValue();                if (v1 == v2)                    return true;            }            return false;        }            public int hashCode() {            Object k = getKey();            Object v = getValue();            return  ((k==null ? 0 : k.hashCode()) ^                     (v==null ? 0 : v.hashCode()));        }            public String toString() {            return getKey() + "=" + getValue();

⌨️ 快捷键说明

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