📄 referencemap.java
字号:
public int size() { purge(); return size; } /** * Returns <code>true</code> if this map is empty. * * @return <code>true</code> if this map is empty */ public boolean isEmpty() { purge(); return size == 0; } /** * Returns <code>true</code> if this map contains the given key. * * @return true if the given key is in this map */ public boolean containsKey(Object key) { purge(); Entry entry = getEntry(key); if (entry == null) return false; return entry.getValue() != null; } /** * Returns the value associated with the given key, if any. * * @return the value associated with the given key, or <code>null</code> * if the key maps to no value */ public Object get(Object key) { purge(); Entry entry = getEntry(key); if (entry == null) return null; return entry.getValue(); } /** * Associates the given key with the given value.<p> * Neither the key nor the value may be null. * * @param key the key of the mapping * @param value the value of the mapping * @return the last value associated with that key, or * null if no value was associated with the key * @throws NullPointerException if either the key or value * is null */ public Object put(Object key, Object value) { if (key == null) throw new NullPointerException("null keys not allowed"); if (value == null) throw new NullPointerException("null values not allowed"); purge(); if (size + 1 > threshold) resize(); int hash = key.hashCode(); int index = indexFor(hash); Entry entry = table[index]; while (entry != null) { if ((hash == entry.hash) && key.equals(entry.getKey())) { Object result = entry.getValue(); entry.setValue(value); return result; } entry = entry.next; } this.size++; modCount++; key = toReference(keyType, key, hash); value = toReference(valueType, value, hash); table[index] = new Entry(key, hash, value, table[index]); return null; } /** * Removes the key and its associated value from this map. * * @param key the key to remove * @return the value associated with that key, or null if * the key was not in the map */ public Object remove(Object key) { if (key == null) return null; purge(); int hash = key.hashCode(); int index = indexFor(hash); Entry previous = null; Entry entry = table[index]; while (entry != null) { if ((hash == entry.hash) && key.equals(entry.getKey())) { if (previous == null) table[index] = entry.next; else previous.next = entry.next; this.size--; modCount++; return entry.getValue(); } previous = entry; entry = entry.next; } return null; } /** * Clears this map. */ public void clear() { Arrays.fill(table, null); size = 0; while (queue.poll() != null); // drain the queue } /** * Returns a set view of this map's entries. * * @return a set view of this map's entries */ public Set entrySet() { if (entrySet != null) { return entrySet; } entrySet = new AbstractSet() { public int size() { return ReferenceMap.this.size(); } public void clear() { ReferenceMap.this.clear(); } public boolean contains(Object o) { if (o == null) return false; if (!(o instanceof Map.Entry)) return false; Map.Entry e = (Map.Entry)o; Entry e2 = getEntry(e.getKey()); return (e2 != null) && e.equals(e2); } public boolean remove(Object o) { boolean r = contains(o); if (r) { Map.Entry e = (Map.Entry)o; ReferenceMap.this.remove(e.getKey()); } return r; } public Iterator iterator() { return new EntryIterator(); } public Object[] toArray() { return toArray(new Object[0]); } public Object[] toArray(Object[] arr) { ArrayList list = new ArrayList(); Iterator iterator = iterator(); while (iterator.hasNext()) { Entry e = (Entry)iterator.next(); list.add(new DefaultMapEntry(e.getKey(), e.getValue())); } return list.toArray(arr); } }; return entrySet; } /** * Returns a set view of this map's keys. * * @return a set view of this map's keys */ public Set keySet() { if (keySet != null) return keySet; keySet = new AbstractSet() { public int size() { return ReferenceMap.this.size(); } public Iterator iterator() { return new KeyIterator(); } public boolean contains(Object o) { return containsKey(o); } public boolean remove(Object o) { Object r = ReferenceMap.this.remove(o); return r != null; } public void clear() { ReferenceMap.this.clear(); } public Object[] toArray() { return toArray(new Object[0]); } public Object[] toArray(Object[] array) { Collection c = new ArrayList(size()); for (Iterator it = iterator(); it.hasNext(); ) { c.add(it.next()); } return c.toArray(array); } }; return keySet; } /** * Returns a collection view of this map's values. * * @return a collection view of this map's values. */ public Collection values() { if (values != null) return values; values = new AbstractCollection() { public int size() { return ReferenceMap.this.size(); } public void clear() { ReferenceMap.this.clear(); } public Iterator iterator() { return new ValueIterator(); } public Object[] toArray() { return toArray(new Object[0]); } public Object[] toArray(Object[] array) { Collection c = new ArrayList(size()); for (Iterator it = iterator(); it.hasNext(); ) { c.add(it.next()); } return c.toArray(array); } }; return values; } // If getKey() or getValue() returns null, it means // the mapping is stale and should be removed. private class Entry implements Map.Entry, KeyValue { Object key; Object value; int hash; Entry next; public Entry(Object key, int hash, Object value, Entry next) { this.key = key; this.hash = hash; this.value = value; this.next = next; } public Object getKey() { return (keyType > HARD) ? ((Reference)key).get() : key; } public Object getValue() { return (valueType > HARD) ? ((Reference)value).get() : value; } public Object setValue(Object object) { Object old = getValue(); if (valueType > HARD) ((Reference)value).clear(); value = toReference(valueType, object, hash); return old; } public boolean equals(Object o) { if (o == null) return false; if (o == this) return true; if (!(o instanceof Map.Entry)) return false; Map.Entry entry = (Map.Entry)o; Object key = entry.getKey(); Object value = entry.getValue(); if ((key == null) || (value == null)) return false; return key.equals(getKey()) && value.equals(getValue()); } public int hashCode() { Object v = getValue(); return hash ^ ((v == null) ? 0 : v.hashCode()); } public String toString() { return getKey() + "=" + getValue(); } boolean purge(Reference ref) { boolean r = (keyType > HARD) && (key == ref); r = r || ((valueType > HARD) && (value == ref)); if (r) { if (keyType > HARD) ((Reference)key).clear(); if (valueType > HARD) { ((Reference)value).clear(); } else if (purgeValues) { value = null; } } return r; } } private class EntryIterator implements Iterator { // These fields keep track of where we are in the table. int index; Entry entry; Entry previous; // These Object fields provide hard references to the // current and next entry; this assures that if hasNext() // returns true, next() will actually return a valid element. Object nextKey, nextValue; Object currentKey, currentValue; int expectedModCount; public EntryIterator() { index = (size() != 0 ? table.length : 0); // have to do this here! size() invocation above // may have altered the modCount. expectedModCount = modCount; } public boolean hasNext() { checkMod(); while (nextNull()) { Entry e = entry; int i = index; while ((e == null) && (i > 0)) { i--; e = table[i]; } entry = e; index = i; if (e == null) { currentKey = null; currentValue = null; return false; } nextKey = e.getKey(); nextValue = e.getValue(); if (nextNull()) entry = entry.next; } return true; } private void checkMod() { if (modCount != expectedModCount) { throw new ConcurrentModificationException(); } } private boolean nextNull() { return (nextKey == null) || (nextValue == null); } protected Entry nextEntry() { checkMod(); if (nextNull() && !hasNext()) throw new NoSuchElementException(); previous = entry; entry = entry.next; currentKey = nextKey; currentValue = nextValue; nextKey = null; nextValue = null; return previous; } public Object next() { return nextEntry(); } public void remove() { checkMod(); if (previous == null) throw new IllegalStateException(); ReferenceMap.this.remove(currentKey); previous = null; currentKey = null; currentValue = null; expectedModCount = modCount; } } private class ValueIterator extends EntryIterator { public Object next() { return nextEntry().getValue(); } } private class KeyIterator extends EntryIterator { public Object next() { return nextEntry().getKey(); } } // These two classes store the hashCode of the key of // of the mapping, so that after they're dequeued a quick // lookup of the bucket in the table can occur. private static class SoftRef extends SoftReference { private int hash; public SoftRef(int hash, Object r, ReferenceQueue q) { super(r, q); this.hash = hash; } public int hashCode() { return hash; } } private static class WeakRef extends WeakReference { private int hash; public WeakRef(int hash, Object r, ReferenceQueue q) { super(r, q); this.hash = hash; } public int hashCode() { return hash; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -