aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/javassist/scopedpool/SoftValueHashMap.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/javassist/scopedpool/SoftValueHashMap.java')
-rw-r--r--src/main/javassist/scopedpool/SoftValueHashMap.java132
1 files changed, 96 insertions, 36 deletions
diff --git a/src/main/javassist/scopedpool/SoftValueHashMap.java b/src/main/javassist/scopedpool/SoftValueHashMap.java
index df6ae599..1154e62e 100644
--- a/src/main/javassist/scopedpool/SoftValueHashMap.java
+++ b/src/main/javassist/scopedpool/SoftValueHashMap.java
@@ -18,10 +18,14 @@ package javassist.scopedpool;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
-import java.util.AbstractMap;
-import java.util.HashMap;
+import java.util.AbstractMap.SimpleImmutableEntry;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
/**
* This Map will remove entries when the value in the map has been cleaned from
@@ -30,21 +34,21 @@ import java.util.Set;
* @version <tt>$Revision: 1.4 $</tt>
* @author <a href="mailto:bill@jboss.org">Bill Burke</a>
*/
-public class SoftValueHashMap extends AbstractMap implements Map {
- private static class SoftValueRef extends SoftReference {
- public Object key;
+public class SoftValueHashMap<K,V> implements Map<K,V> {
+ private static class SoftValueRef<K,V> extends SoftReference<V> {
+ public K key;
- private SoftValueRef(Object key, Object val, ReferenceQueue q) {
+ private SoftValueRef(K key, V val, ReferenceQueue<V> q) {
super(val, q);
this.key = key;
}
- private static SoftValueRef create(Object key, Object val,
- ReferenceQueue q) {
+ private static <K,V> SoftValueRef<K,V> create(
+ K key, V val, ReferenceQueue<V> q) {
if (val == null)
return null;
else
- return new SoftValueRef(key, val, q);
+ return new SoftValueRef<K,V>(key, val, q);
}
}
@@ -52,30 +56,37 @@ public class SoftValueHashMap extends AbstractMap implements Map {
/**
* Returns a set of the mappings contained in this hash table.
*/
- public Set entrySet() {
+ @Override
+ public Set<Map.Entry<K, V>> entrySet() {
processQueue();
- return hash.entrySet();
+ Set<Entry<K,V>> ret = new HashSet<Entry<K,V>>();
+ for (Entry<K,SoftValueRef<K,V>> e:hash.entrySet())
+ ret.add(new SimpleImmutableEntry<K,V> (
+ e.getKey(), e.getValue().get()));
+ return ret;
}
/* Hash table mapping WeakKeys to values */
- private Map hash;
+ private Map<K,SoftValueRef<K,V>> hash;
/* Reference queue for cleared WeakKeys */
- private ReferenceQueue queue = new ReferenceQueue();
+ private ReferenceQueue<V> queue = new ReferenceQueue<V>();
/*
* Remove all invalidated entries from the map, that is, remove all entries
* whose values have been discarded.
*/
private void processQueue() {
- SoftValueRef ref;
- while ((ref = (SoftValueRef)queue.poll()) != null) {
- if (ref == (SoftValueRef)hash.get(ref.key)) {
- // only remove if it is the *exact* same WeakValueRef
- //
- hash.remove(ref.key);
+ Object ref;
+ if (!hash.isEmpty())
+ while ((ref = queue.poll()) != null)
+ if (ref instanceof SoftValueRef) {
+ @SuppressWarnings("rawtypes")
+ SoftValueRef que =(SoftValueRef) ref;
+ if (ref == hash.get(que.key))
+ // only remove if it is the *exact* same SoftValueRef
+ hash.remove(que.key);
}
- }
}
/* -- Constructors -- */
@@ -95,7 +106,7 @@ public class SoftValueHashMap extends AbstractMap implements Map {
* factor is nonpositive
*/
public SoftValueHashMap(int initialCapacity, float loadFactor) {
- hash = new HashMap(initialCapacity, loadFactor);
+ hash = new ConcurrentHashMap<K,SoftValueRef<K,V>>(initialCapacity, loadFactor);
}
/**
@@ -109,7 +120,7 @@ public class SoftValueHashMap extends AbstractMap implements Map {
* If the initial capacity is less than zero
*/
public SoftValueHashMap(int initialCapacity) {
- hash = new HashMap(initialCapacity);
+ hash = new ConcurrentHashMap<K,SoftValueRef<K,V>>(initialCapacity);
}
/**
@@ -117,7 +128,7 @@ public class SoftValueHashMap extends AbstractMap implements Map {
* initial capacity and the default load factor, which is <code>0.75</code>.
*/
public SoftValueHashMap() {
- hash = new HashMap();
+ hash = new ConcurrentHashMap<K,SoftValueRef<K,V>>();
}
/**
@@ -129,7 +140,7 @@ public class SoftValueHashMap extends AbstractMap implements Map {
*
* @param t the map whose mappings are to be placed in this map.
*/
- public SoftValueHashMap(Map t) {
+ public SoftValueHashMap(Map<K,V> t) {
this(Math.max(2 * t.size(), 11), 0.75f);
putAll(t);
}
@@ -142,6 +153,7 @@ public class SoftValueHashMap extends AbstractMap implements Map {
* <code>Map</code> interface, the time required by this operation is
* linear in the size of the map.</em>
*/
+ @Override
public int size() {
processQueue();
return hash.size();
@@ -150,6 +162,7 @@ public class SoftValueHashMap extends AbstractMap implements Map {
/**
* Returns <code>true</code> if this map contains no key-value mappings.
*/
+ @Override
public boolean isEmpty() {
processQueue();
return hash.isEmpty();
@@ -162,6 +175,7 @@ public class SoftValueHashMap extends AbstractMap implements Map {
* @param key
* The key whose presence in this map is to be tested.
*/
+ @Override
public boolean containsKey(Object key) {
processQueue();
return hash.containsKey(key);
@@ -177,12 +191,10 @@ public class SoftValueHashMap extends AbstractMap implements Map {
* @param key
* The key whose associated value, if any, is to be returned.
*/
- public Object get(Object key) {
+ @Override
+ public V get(Object key) {
processQueue();
- SoftReference ref = (SoftReference)hash.get(key);
- if (ref != null)
- return ref.get();
- return null;
+ return valueOrNull(hash.get(key));
}
/**
@@ -200,12 +212,10 @@ public class SoftValueHashMap extends AbstractMap implements Map {
* @return The previous value to which this key was mapped, or
* <code>null</code> if if there was no mapping for the key
*/
- public Object put(Object key, Object value) {
+ @Override
+ public V put(K key, V value) {
processQueue();
- Object rtn = hash.put(key, SoftValueRef.create(key, value, queue));
- if (rtn != null)
- rtn = ((SoftReference)rtn).get();
- return rtn;
+ return valueOrNull(hash.put(key, SoftValueRef.create(key, value, queue)));
}
/**
@@ -218,16 +228,66 @@ public class SoftValueHashMap extends AbstractMap implements Map {
* @return The value to which this key was mapped, or <code>null</code> if
* there was no mapping for the key.
*/
- public Object remove(Object key) {
+ @Override
+ public V remove(Object key) {
processQueue();
- return hash.remove(key);
+ return valueOrNull(hash.remove(key));
}
/**
* Removes all mappings from this map.
*/
+ @Override
public void clear() {
processQueue();
hash.clear();
}
+
+ /*
+ * Check whether the supplied value exists.
+ * @param Object the value to compare.
+ * @return true if it was found or null.
+ */
+ @Override
+ public boolean containsValue(Object arg0) {
+ processQueue();
+ if (null == arg0)
+ return false;
+
+ for (SoftValueRef<K,V> e:hash.values())
+ if (null != e && arg0.equals(e.get()))
+ return true;
+ return false;
+ }
+
+ /* {@inheritDoc} */
+ @Override
+ public Set<K> keySet() {
+ processQueue();
+ return hash.keySet();
+ }
+
+ /* {@inheritDoc} */
+ @Override
+ public void putAll(Map<? extends K,? extends V> arg0) {
+ processQueue();
+ for (K key:arg0.keySet())
+ put(key, arg0.get(key));
+ }
+
+ /* {@inheritDoc} */
+ @Override
+ public Collection<V> values() {
+ processQueue();
+ List<V> ret = new ArrayList<V>();
+ for (SoftValueRef<K,V> e:hash.values())
+ ret.add(e.get());
+ return ret;
+ }
+
+ private V valueOrNull(SoftValueRef<K,V> rtn) {
+ if (null == rtn)
+ return null;
+ return rtn.get();
+ }
}