WeakHashMap for values

H

Hendrik Maryns

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

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
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (GNU/Linux)

iD4DBQFEiEoNe+7xMGD3itQRAimdAJiJ2EnFnfL3x5/yKkhP309ok4LlAJ4sWKJs
zwM7OKrbnf4YScBMJShK2w==
=EIP6
-----END PGP SIGNATURE-----
 
R

Rogan Dawes

Hendrik said:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

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!


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
 
T

Thomas Hawtin

Hendrik said:
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?
[...]
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.

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
 
H

Hendrik Maryns

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Rogan Dawes schreef:
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 {

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/c...che/commons/collections/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
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (GNU/Linux)

iD8DBQFEiFMIe+7xMGD3itQRAiXLAJ9bRsFzfGEF124rBlxZWJiTDC76AQCfbsp2
pNB0623bHro89vszju1DQ/o=
=3tsL
-----END PGP SIGNATURE-----
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,982
Messages
2,570,186
Members
46,739
Latest member
Clint8040

Latest Threads

Top