📄 weakhashtable.java
字号:
Referenced keyRef = new Referenced(key, queue);
return super.put(keyRef, value);
}
/**
*@see Hashtable
*/
public void putAll(Map t) {
if (t != null) {
Set entrySet = t.entrySet();
for (Iterator it=entrySet.iterator(); it.hasNext();) {
Map.Entry entry = (Map.Entry) it.next();
put(entry.getKey(), entry.getValue());
}
}
}
/**
*@see Hashtable
*/
public Collection values() {
purge();
return super.values();
}
/**
*@see Hashtable
*/
public Object remove(Object key) {
// for performance reasons, only purge every
// MAX_CHANGES_BEFORE_PURGE times
if (changeCount++ > MAX_CHANGES_BEFORE_PURGE) {
purge();
changeCount = 0;
}
// do a partial purge more often
else if ((changeCount % PARTIAL_PURGE_COUNT) == 0) {
purgeOne();
}
return super.remove(new Referenced(key));
}
/**
*@see Hashtable
*/
public boolean isEmpty() {
purge();
return super.isEmpty();
}
/**
*@see Hashtable
*/
public int size() {
purge();
return super.size();
}
/**
*@see Hashtable
*/
public String toString() {
purge();
return super.toString();
}
/**
* @see Hashtable
*/
protected void rehash() {
// purge here to save the effort of rehashing dead entries
purge();
super.rehash();
}
/**
* Purges all entries whose wrapped keys
* have been garbage collected.
*/
private void purge() {
synchronized (queue) {
WeakKey key;
while ((key = (WeakKey) queue.poll()) != null) {
super.remove(key.getReferenced());
}
}
}
/**
* Purges one entry whose wrapped key
* has been garbage collected.
*/
private void purgeOne() {
synchronized (queue) {
WeakKey key = (WeakKey) queue.poll();
if (key != null) {
super.remove(key.getReferenced());
}
}
}
/** Entry implementation */
private final static class Entry implements Map.Entry {
private final Object key;
private final Object value;
private Entry(Object key, Object value) {
this.key = key;
this.value = value;
}
public boolean equals(Object o) {
boolean result = false;
if (o != null && o instanceof Map.Entry) {
Map.Entry entry = (Map.Entry) o;
result = (getKey()==null ?
entry.getKey() == null :
getKey().equals(entry.getKey()))
&&
(getValue()==null ?
entry.getValue() == null :
getValue().equals(entry.getValue()));
}
return result;
}
public int hashCode() {
return (getKey()==null ? 0 : getKey().hashCode()) ^
(getValue()==null ? 0 : getValue().hashCode());
}
public Object setValue(Object value) {
throw new UnsupportedOperationException("Entry.setValue is not supported.");
}
public Object getValue() {
return value;
}
public Object getKey() {
return key;
}
}
/** Wrapper giving correct symantics for equals and hashcode */
private final static class Referenced {
private final WeakReference reference;
private final int hashCode;
/**
*
* @throws NullPointerException if referant is <code>null</code>
*/
private Referenced(Object referant) {
reference = new WeakReference(referant);
// Calc a permanent hashCode so calls to Hashtable.remove()
// work if the WeakReference has been cleared
hashCode = referant.hashCode();
}
/**
*
* @throws NullPointerException if key is <code>null</code>
*/
private Referenced(Object key, ReferenceQueue queue) {
reference = new WeakKey(key, queue, this);
// Calc a permanent hashCode so calls to Hashtable.remove()
// work if the WeakReference has been cleared
hashCode = key.hashCode();
}
public int hashCode() {
return hashCode;
}
private Object getValue() {
return reference.get();
}
public boolean equals(Object o) {
boolean result = false;
if (o instanceof Referenced) {
Referenced otherKey = (Referenced) o;
Object thisKeyValue = getValue();
Object otherKeyValue = otherKey.getValue();
if (thisKeyValue == null) {
result = (otherKeyValue == null);
// Since our hashcode was calculated from the original
// non-null referant, the above check breaks the
// hashcode/equals contract, as two cleared Referenced
// objects could test equal but have different hashcodes.
// We can reduce (not eliminate) the chance of this
// happening by comparing hashcodes.
if (result == true) {
result = (this.hashCode() == otherKey.hashCode());
}
// In any case, as our c'tor does not allow null referants
// and Hashtable does not do equality checks between
// existing keys, normal hashtable operations should never
// result in an equals comparison between null referants
}
else
{
result = thisKeyValue.equals(otherKeyValue);
}
}
return result;
}
}
/**
* WeakReference subclass that holds a hard reference to an
* associated <code>value</code> and also makes accessible
* the Referenced object holding it.
*/
private final static class WeakKey extends WeakReference {
private final Referenced referenced;
private WeakKey(Object key,
ReferenceQueue queue,
Referenced referenced) {
super(key, queue);
this.referenced = referenced;
}
private Referenced getReferenced() {
return referenced;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -