Hi,
I need something like WeakHashMap, but with the inverse function: I want
the values to be weakly referenced to, and the entry to be discarded
from the map once the value no longer exists. Is there a standard
implementation for this?
But maybe, as happens often, I am saying: I want X, whereas actually I
want Y, but think I need X to achieve it. So here is my real problem:
I have some small wrapper objects, whose identity is determined by the
array of some other objects they contain. I want to avoid unnecessary
implementations of those wrappers, so I wanted to write a factory
method. The first idea is to have a Map mapping lists to objects
(arrays do not give good hash codes, so I convert them with
Arrays.asList first). Now, the whole idea is to save memory, so I don’t
want this map to get unnecessarily big. The idea is: using weak
references I can have it clean up itself. But WeakHashMap does just the
inverse: it weakly wraps the key, not the value. And using the
suggestion in the javadoc will not work too, I think: I can wrap the
values myself, but the keys are lists made on the fly, so the weak hash
map will throw those entries away too soon!
One solution I see, is to use an ordinary HashMap, wrap the values in
weak references, and do some cleanup in the map from time to time. But
I am not sure how I should implement ‘from time to time’, then.
Suggestions welcome!
TIA, H.
- --
Hendrik Maryns
==================
http://aouw.org
Ask smart questions, get good answers:
http://www.catb.org/~esr/faqs/smart-questions.html
Rogan Dawes - 08 Jun 2006 17:30 GMT
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
[quoted text clipped - 27 lines]
>
> Suggestions welcome!
Depending on the size of your HashMap, you could do it whenever someone
gets or puts a value.
e.g. if they do
map.get(foo), and the value referenced by foo has gone away, simply
return null, and remove the entry for foo from the map.
e.g. (typed in my mail client, and not carefully checked)
public class WeakValueHashMap extends HashMap {
// necessary constructors . . .
public Object put(Object key, Object value) {
WeakReference old = null;
if (value != null) {
old = (WeakReference) super.put(key, new WeakReference(value));
} else {
old = (WeakReference) super.put(key, null);
}
if (old != null) {
return old.get();
}
return null;
}
public Object get(Object key) {
WeakReference value = (WeakReference) super.get(key);
if (value == null) return null;
return value.get();
}
private void prune() {
Iterator it = keySet().iterator();
while (it.hasNext()) {
Object key = it.next();
WeakReference value = super.get(key);
if (value != null && value.get() == null) {
it.remove();
}
}
}
}
Depending on how you plan to use the class, you should probably wrap
calls to entrySet, keySet() and values(), etc with a call to prune
first, as well as making sure that each of the values returned have been
suitably dereferenced.
Hope this helped.
Rogan
Hendrik Maryns - 08 Jun 2006 17:40 GMT
Rogan Dawes schreef:
>> -----BEGIN PGP SIGNED MESSAGE-----
>> Hash: SHA1
[quoted text clipped - 39 lines]
>
> public class WeakValueHashMap extends HashMap {
Thanks for the code, though I wouldn’t have it extend HashMap, as it
breaks some contracts.
However, I found
http://jakarta.apache.org/commons/collections/apidocs/org/apache/commons/collect
ions/map/ReferenceMap.html,
and decided to use this first. But I keep your suggestions in mind,
thanks both!
H.
- --
Hendrik Maryns
==================
http://aouw.org
Ask smart questions, get good answers:
http://www.catb.org/~esr/faqs/smart-questions.html
Thomas Hawtin - 08 Jun 2006 17:30 GMT
> I need something like WeakHashMap, but with the inverse function: I want
> the values to be weakly referenced to, and the entry to be discarded
[quoted text clipped - 4 lines]
> weak references, and do some cleanup in the map from time to time. But
> I am not sure how I should implement ‘from time to time’, then.
I suggest taking a look at the source for WeakHashMap.
The obvious way of going about this is to use a subclass of
WeakReference for the values. The subclass should just keep a strong
reference to the key.
Pass a ReferenceQueue through the WeakReference constructor. Poll the
queue whenever you use the map. If you get a WeakReference returned,
cast it to your subclass and remove from the map using the strong
reference to the key.
Tom Hawtin

Signature
Unemployed English Java programmer
http://jroller.com/page/tackline/