📄 abstractreferencemap.java
字号:
//-----------------------------------------------------------------------
/**
* Purges stale mappings from this map before read operations.
* <p>
* This implementation calls {@link #purge()} to maintain a consistent state.
*/
protected void purgeBeforeRead() {
purge();
}
/**
* Purges stale mappings from this map before write operations.
* <p>
* This implementation calls {@link #purge()} to maintain a consistent state.
*/
protected void purgeBeforeWrite() {
purge();
}
/**
* Purges stale mappings from this map.
* <p>
* Note that this method is not synchronized! Special
* care must be taken if, for instance, you want stale
* mappings to be removed on a periodic basis by some
* background thread.
*/
protected void purge() {
Reference ref = queue.poll();
while (ref != null) {
purge(ref);
ref = queue.poll();
}
}
/**
* Purges the specified reference.
*
* @param ref the reference to purge
*/
protected void purge(Reference ref) {
// The hashCode of the reference is the hashCode of the
// mapping key, even if the reference refers to the
// mapping value...
int hash = ref.hashCode();
int index = hashIndex(hash, data.length);
HashEntry previous = null;
HashEntry entry = data[index];
while (entry != null) {
if (((ReferenceEntry) entry).purge(ref)) {
if (previous == null) {
data[index] = entry.next;
} else {
previous.next = entry.next;
}
this.size--;
return;
}
previous = entry;
entry = entry.next;
}
}
//-----------------------------------------------------------------------
/**
* Gets the entry mapped to the key specified.
*
* @param key the key
* @return the entry, null if no match
*/
protected HashEntry getEntry(Object key) {
if (key == null) {
return null;
} else {
return super.getEntry(key);
}
}
/**
* Gets the hash code for a MapEntry.
* Subclasses can override this, for example to use the identityHashCode.
*
* @param key the key to get a hash code for, may be null
* @param value the value to get a hash code for, may be null
* @return the hash code, as per the MapEntry specification
*/
protected int hashEntry(Object key, Object value) {
return (key == null ? 0 : key.hashCode()) ^
(value == null ? 0 : value.hashCode());
}
/**
* Compares two keys, in internal converted form, to see if they are equal.
* <p>
* This implementation converts the key from the entry to a real reference
* before comparison.
*
* @param key1 the first key to compare passed in from outside
* @param key2 the second key extracted from the entry via <code>entry.key</code>
* @return true if equal
*/
protected boolean isEqualKey(Object key1, Object key2) {
key2 = (keyType > HARD ? ((Reference) key2).get() : key2);
return (key1 == key2 || key1.equals(key2));
}
/**
* Creates a ReferenceEntry instead of a HashEntry.
*
* @param next the next entry in sequence
* @param hashCode the hash code to use
* @param key the key to store
* @param value the value to store
* @return the newly created entry
*/
protected HashEntry createEntry(HashEntry next, int hashCode, Object key, Object value) {
return new ReferenceEntry(this, next, hashCode, key, value);
}
/**
* Creates an entry set iterator.
*
* @return the entrySet iterator
*/
protected Iterator createEntrySetIterator() {
return new ReferenceEntrySetIterator(this);
}
/**
* Creates an key set iterator.
*
* @return the keySet iterator
*/
protected Iterator createKeySetIterator() {
return new ReferenceKeySetIterator(this);
}
/**
* Creates an values iterator.
*
* @return the values iterator
*/
protected Iterator createValuesIterator() {
return new ReferenceValuesIterator(this);
}
//-----------------------------------------------------------------------
/**
* EntrySet implementation.
*/
static class ReferenceEntrySet extends EntrySet {
protected ReferenceEntrySet(AbstractHashedMap parent) {
super(parent);
}
public Object[] toArray() {
return toArray(new Object[0]);
}
public Object[] toArray(Object[] arr) {
// special implementation to handle disappearing entries
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);
}
}
//-----------------------------------------------------------------------
/**
* KeySet implementation.
*/
static class ReferenceKeySet extends KeySet {
protected ReferenceKeySet(AbstractHashedMap parent) {
super(parent);
}
public Object[] toArray() {
return toArray(new Object[0]);
}
public Object[] toArray(Object[] arr) {
// special implementation to handle disappearing keys
List list = new ArrayList(parent.size());
for (Iterator it = iterator(); it.hasNext(); ) {
list.add(it.next());
}
return list.toArray(arr);
}
}
//-----------------------------------------------------------------------
/**
* Values implementation.
*/
static class ReferenceValues extends Values {
protected ReferenceValues(AbstractHashedMap parent) {
super(parent);
}
public Object[] toArray() {
return toArray(new Object[0]);
}
public Object[] toArray(Object[] arr) {
// special implementation to handle disappearing values
List list = new ArrayList(parent.size());
for (Iterator it = iterator(); it.hasNext(); ) {
list.add(it.next());
}
return list.toArray(arr);
}
}
//-----------------------------------------------------------------------
/**
* A MapEntry implementation for the map.
* <p>
* If getKey() or getValue() returns null, it means
* the mapping is stale and should be removed.
*
* @since Commons Collections 3.1
*/
protected static class ReferenceEntry extends HashEntry {
/** The parent map */
protected final AbstractReferenceMap parent;
/**
* Creates a new entry object for the ReferenceMap.
*
* @param parent the parent map
* @param next the next entry in the hash bucket
* @param hashCode the hash code of the key
* @param key the key
* @param value the value
*/
public ReferenceEntry(AbstractReferenceMap parent, HashEntry next, int hashCode, Object key, Object value) {
super(next, hashCode, null, null);
this.parent = parent;
this.key = toReference(parent.keyType, key, hashCode);
this.value = toReference(parent.valueType, value, hashCode); // the key hashCode is passed in deliberately
}
/**
* Gets the key from the entry.
* This method dereferences weak and soft keys and thus may return null.
*
* @return the key, which may be null if it was garbage collected
*/
public Object getKey() {
return (parent.keyType > HARD) ? ((Reference) key).get() : key;
}
/**
* Gets the value from the entry.
* This method dereferences weak and soft value and thus may return null.
*
* @return the value, which may be null if it was garbage collected
*/
public Object getValue() {
return (parent.valueType > HARD) ? ((Reference) value).get() : value;
}
/**
* Sets the value of the entry.
*
* @param obj the object to store
* @return the previous value
*/
public Object setValue(Object obj) {
Object old = getValue();
if (parent.valueType > HARD) {
((Reference)value).clear();
}
value = toReference(parent.valueType, obj, hashCode);
return old;
}
/**
* Compares this map entry to another.
* <p>
* This implementation uses <code>isEqualKey</code> and
* <code>isEqualValue</code> on the main map for comparison.
*
* @param obj the other map entry to compare to
* @return true if equal, false if not
*/
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj instanceof Map.Entry == false) {
return false;
}
Map.Entry entry = (Map.Entry)obj;
Object entryKey = entry.getKey(); // convert to hard reference
Object entryValue = entry.getValue(); // convert to hard reference
if ((entryKey == null) || (entryValue == null)) {
return false;
}
// compare using map methods, aiding identity subclass
// note that key is direct access and value is via method
return parent.isEqualKey(entryKey, key) &&
parent.isEqualValue(entryValue, getValue());
}
/**
* Gets the hashcode of the entry using temporary hard references.
* <p>
* This implementation uses <code>hashEntry</code> on the main map.
*
* @return the hashcode of the entry
*/
public int hashCode() {
return parent.hashEntry(getKey(), getValue());
}
/**
* Constructs a reference of the given type to the given referent.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -