📄 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 + -