Java Weak Hash Map - Need to remove entry based on weakness of value, not key
So the Java WeakHashMap
lets one create a map whose entries are removed if its keys become weak. But how can I create a Map whose entries are removed when the values in the map become weak? The reason I want to use a map is as a Global Hash Table which keeps track of objects according to their ID's.
ID ---> Object Address
Key ---> Value
(W开发者_高级运维here ID
is a text string)
I want key-value pairs to be removed when the object addresses become weak, not the Strings that point to them. Anyone any thoughts on this?
Such a map is supported, for example, in Guava:
Map<..., ...> m = new MapMaker().weakValues().makeMap();
Why do you want the entry to be garbage collected ? I see two reasons
- avoid memory leaks (avoid to keep a weakReference pointing to nothing in your Map)
- myMap.get(myKey) should return null if the object was garbage collected.
Solution use a regular HashMap:
Map<String, WeakReference<Object>>
then if 2) is the sole problem just use myMap.get(myKey).get()
If you need to also remove the entries have a look at this post that describes a softHashMap and adapt it to use weakReferences...
The API has the answer:
Implementation note: The value objects in a WeakHashMap are held by ordinary strong references. Thus care should be taken to ensure that value objects do not strongly refer to their own keys, either directly or indirectly, since that will prevent the keys from being discarded. Note that a value object may refer indirectly to its key via the WeakHashMap itself; that is, a value object may strongly refer to some other key object whose associated value object, in turn, strongly refers to the key of the first value object. One way to deal with this is to wrap values themselves within WeakReferences before inserting, as in:
m.put(key, new WeakReference(value))
, and then unwrapping upon each get.
You can do what WeakHashMap does, but to values instead of keys: wrap your values in WeakReferences, and associate them with a ReferenceQueue held in the map. Whenever the map is accessed, check the ReferenceQueue to see if anything has been added, and if it has, remove its entry from the map. You'll need to make a subclass of WeakReference that holds the key, so you know which entry to remove. You will also need to add a check to methods which query the map (get and containsKey, the iterator methods, etc) to check that a retrieved WeakReference actually contains a value (remember to either ban null values, or use a special sentinel object to represent them).
精彩评论