File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes Java in General and the fly likes Question on WeakHashMap Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Android Security Essentials Live Lessons this week in the Android forum!
JavaRanch » Java Forums » Java » Java in General
Bookmark "Question on WeakHashMap" Watch "Question on WeakHashMap" New topic
Author

Question on WeakHashMap

Alejandro Barrero
Ranch Hand

Joined: Aug 01, 2005
Posts: 309
I understand how a WeakHashMap works; if a key no longer has strong references, the associated object is removed (and probably will no longer have strong references). I see how this would be useful storing large objects like images.

But the problem I have with this is that the keys must at some time have no strong references. The program has to have references to the keys in order to retrieve the objects; a key will stop being useful only when the program knows that it would not be needed again but that is the same problem as determining that an object would not be needed again. I just don't see how a WeakHashMap would work in practice.


Your help will be greatly appreciated,
Alejandro Barrero
Stephan van Hulst
Bartender

Joined: Sep 20, 2010
Posts: 3605
    
  14

Hi Alejandro.

It works because keys are checked for equality, not identity.

Let's assume Map<Path, Image> cache = new WeakHashMap<>(); if the program doesn't have any strong references to the file path, the map is free to delete the entry. However, we can still create a new path that is equal to the old one, and use that to retrieve the image from the map (if the entry still exists).

Note that you can have strong references to the images themselves, this won't prevent them from being deleted from the map.
Stephan van Hulst
Bartender

Joined: Sep 20, 2010
Posts: 3605
    
  14

Also note that you have to take precautions if you want to use certain data types as keys. For instance, Strings and integer objects may be interned, and will have strong references to them regardless of whether your program uses them.

If you have a Map<String, Image>, you should probably save entries like this:
This will prevent that the keys in the map will be interned, and so the entry can be deleted if you lose the reference to key.
Jeff Verdegan
Bartender

Joined: Jan 03, 2004
Posts: 6109
    
    6

Stephan van Hulst wrote:Hi Alejandro.

It works because keys are checked for equality, not identity.


It's true that keys are checked for equality, not identity, but the docs say, "This class is intended primarily for use with key objects whose equals methods test for object identity using the == operator", so that's not why it works.

It works because the map stores weak references to the keys, so that once our code holds no more strong reference to a key, that entry can be automatically removed.

Alejandro Barrero wrote:a key will stop being useful only when the program knows that it would not be needed again but that is the same problem as determining that an object would not be needed again


Not exactly. If we decouple the part of an app that retrieves data from the part that uses it (as we should) then the user of the data won't know about the map and the map code won't know when the rest of the app is done using it. The DAO can have a WeakHashMap member variable that it populates with objects it retrieves to use as a cache. As long as the app is holding on to the keys for those objects somewhere (even if it's not holding on to the value objects themselves), any future lookups can pull the object right from the map. Once the app lets go of the key the DAO's WeakHashMap cache can automatically drop the entry. The rest of the app never needs to know about it.
Alejandro Barrero
Ranch Hand

Joined: Aug 01, 2005
Posts: 309
Thank you very much for your answers. However, my conundrum continues. The documentation states " An entry in a WeakHashMap will automatically be removed when its key is no longer in ordinary use." To me this implies that the client code has to maintain a reference to the key until the objects is not needed any more, but if the program can do this it could simply remove the object.
Jeff Verdegan
Bartender

Joined: Jan 03, 2004
Posts: 6109
    
    6

Alejandro Barrero wrote:To me this implies that the client code has to maintain a reference to the key until the objects is not needed any more, but if the program can do this it could simply remove the object.


No, on two counts.

1. The app doesn't have to maintain the key. But if it happens to do so, then future lookups will be quicker, because they'll be fetched from the map. (Assuming we're talking map as local cache against lookup from DB or some such service.) If it doesn't maintain the key, then the next lookup will incur the cost of going out to the remote data source.

2. The app in general doesn't know about the existence of the WHM. That's a hidden implementation detail of the DAO. This goes back to the decoupling I mentioned.

So if the app has an object, looks up some supplementary info about that object, does some other work that lets the supplementary info get GCed but hangs onto the original (key) object, then decides it needs the supplemental info again, the DAO will already have it cached. After that, if the app lets go of the key, the DAO will also release the K/V mapping, without the app having to know that it was ever mapped in the first place.
Alejandro Barrero
Ranch Hand

Joined: Aug 01, 2005
Posts: 309
I am afraid I need some illumination; If the application can determine when a key is no longer needed, then why not simply used a plain HashMap?
Jeff Verdegan
Bartender

Joined: Jan 03, 2004
Posts: 6109
    
    6

Alejandro Barrero wrote:I am afraid I need some illumination; If the application can determine when a key is no longer needed, then why not simply used a plain HashMap?


1. The app isn't necessarily deciding the key is no longer needed. Or, conversely, up until the time it decides it's no longer needed, it's not necessarily explicitly deciding that it is still needed.

2. The app may decide that the key is still needed, but may choose to let go of the value. If it keeps the key, then the value can be retrieved quickly.

3. There may be separate, independent sections of the app, running in separate threads. A theoretical sequence might be: T1 obtains key. T1 gets value. T2 obtains key. T1 releases key. T2 gets value (quickly, from the Map).

4. Again, the point is decoupling, and separation of responsibilities. The app knows it can get the value when needed. It doesn't know or care if it comes from cache or a remote data store. It also doesn't know or care what other parts of the app may currently be interested in that key and/or its value. The DAO's job is to provide efficient access to requested values when possible. That's why it maintains the cache.
drac yang
Ranch Hand

Joined: Apr 19, 2013
Posts: 61
From jGuru:

A WeakHashMap is a special Map implementation where the keys of the map are stored in a java.lang.ref.WeakReference. By storing the keys in a weak reference, key-value pairs can dynamically be dropped from the map when the only reference to the key is from the weak reference. This makes the WeakHashMap an excellent implementation for a weakly referenced list, where entries that aren't used elsewhere may be dropped with no side effects. Also, just because a key may be dropped, doesn't mean it will immediately be dropped. If the system has sufficient resources, the weak key reference that isn't externally referenced could stay around for a long time.

More on References:

science belief, great bioscience!
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 18553
    
  40

Jeff Verdegan wrote:
Alejandro Barrero wrote:I am afraid I need some illumination; If the application can determine when a key is no longer needed, then why not simply used a plain HashMap?


1. The app isn't necessarily deciding the key is no longer needed. Or, conversely, up until the time it decides it's no longer needed, it's not necessarily explicitly deciding that it is still needed.

2. The app may decide that the key is still needed, but may choose to let go of the value. If it keeps the key, then the value can be retrieved quickly.

3. There may be separate, independent sections of the app, running in separate threads. A theoretical sequence might be: T1 obtains key. T1 gets value. T2 obtains key. T1 releases key. T2 gets value (quickly, from the Map).

4. Again, the point is decoupling, and separation of responsibilities. The app knows it can get the value when needed. It doesn't know or care if it comes from cache or a remote data store. It also doesn't know or care what other parts of the app may currently be interested in that key and/or its value. The DAO's job is to provide efficient access to requested values when possible. That's why it maintains the cache.



I think that the problem that the OP is having is understanding how it works, and not what it is supposed to be doing? So, let me try it from that position.... and BTW, Jeff's statements are correct; this is just a response on the implementation details.

The weak hashmap stores the key using a weak reference, while maintaining a hard reference on the value. If, while doing any operation, it encounters a key object that refers to a null referent, then the key and the value objects are removed from the weakhashmap. Weak hashmaps also has the concept of a reference queue. The garbage collector places any weakreference objects whose referent has been collected into this queue. When the weak hashmap sees any weak references in this queue, it will delete the weak reference key (and the value reference) from the hashmap.

I guess the key phrase from the previous paragraph is the mention of the garbage collector. Yes, if an application can figure out when a key/value pair is no longer needed, then it can use a regular hashmap. But if it can't (or it is too hard to), it can keep a weak reference to it, and later, if it is needed, it can still get it, provided that the garbage collector hasn't gotten to it first. Using a regular hashmap in this case, will prevent the GC from collecting it, regardless of whether the application needs it or not.

Henry

Books: Java Threads, 3rd Edition, Jini in a Nutshell, and Java Gems (contributor)
Alejandro Barrero
Ranch Hand

Joined: Aug 01, 2005
Posts: 309
Thank you all, but it still looks nebulous to me. " But if it can't (or it is too hard to), it can keep a weak reference to it, and later, if it is needed, it can still get it, provided that the garbage collector hasn't gotten to it first. Using a regular hashmap in this case, will prevent the GC from collecting it, regardless of whether the application needs it or not." This is saying that that the client doesn't keep a strong reference to the key {" it can keep a weak reference to it"). That means that the object may be removed from the map at any time but if the application is lucky it may still be there if it is needed again (" it can still get it"). If this is what I have to understand, I understand it. It doesn't ,however, appear as a very solid general solution.

Thanks again.
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 18553
    
  40

Alejandro Barrero wrote:Thank you all, but it still looks nebulous to me. " But if it can't (or it is too hard to), it can keep a weak reference to it, and later, if it is needed, it can still get it, provided that the garbage collector hasn't gotten to it first. Using a regular hashmap in this case, will prevent the GC from collecting it, regardless of whether the application needs it or not." This is saying that that the client doesn't keep a strong reference to the key {" it can keep a weak reference to it"). That means that the object may be removed from the map at any time but if the application is lucky it may still be there if it is needed again (" it can still get it"). If this is what I have to understand, I understand it. It doesn't ,however, appear as a very solid general solution.


I am going out on a limb here and assume that you are from a C/C++ background. When I code in C/C++, this is a situation that doesn't happen often, if at all. However, with Java (and with C#, which admittedly, I am starting to like a lot), where there is a garbage collector, creating an object asymmetrically is common. It is common to create an object and returning it -- and not caring about when the other part of the application is done with it. When it is done with it, the garbage collector will clean up after it.

However, this makes caching harder (since the library doesn't know when the calling part of the application will be done with the instance). If yet another part of the application uses the same library, caching is great, but what to cache? if you cache everything, then you waste memory. If you cache too little, then there will be parts of the applications that have different instances that does the same thing... hence, weak references and implementations such as weak hashmaps, that provides tighter integration with the garbage collector, are used.

Henry
Jeff Verdegan
Bartender

Joined: Jan 03, 2004
Posts: 6109
    
    6

Alejandro Barrero wrote:That means that the object may be removed from the map at any time but if the application is lucky it may still be there if it is needed again (" it can still get it"). If this is what I have to understand, I understand it. It doesn't ,however, appear as a very solid general solution.


That's exactly how caching works. I ask for something, and if it's available locally, I get it quickly. Otherwise, it has to be fetched or re-created more expensively.
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 18553
    
  40

Jeff Verdegan wrote:
Alejandro Barrero wrote:That means that the object may be removed from the map at any time but if the application is lucky it may still be there if it is needed again (" it can still get it"). If this is what I have to understand, I understand it. It doesn't ,however, appear as a very solid general solution.


That's exactly how caching works. I ask for something, and if it's available locally, I get it quickly. Otherwise, it has to be fetched or re-created more expensively.


Yeah, it does appear that the OP is having difficulty with the concept of caching versus the idea of how it is done with weak hashmaps -- sorry for my minor tangent.

Henry
Alejandro Barrero
Ranch Hand

Joined: Aug 01, 2005
Posts: 309
The questions is my statement correct?

That means that the object may be removed from the map at any time but if the application is lucky it may still be there if it is needed again (" it can still get it").
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 18553
    
  40

Alejandro Barrero wrote:The questions is my statement correct?

That means that the object may be removed from the map at any time but if the application is lucky it may still be there if it is needed again (" it can still get it").



Didn't Jeff confirm this, a few posts back?

Henry
Jeff Verdegan
Bartender

Joined: Jan 03, 2004
Posts: 6109
    
    6

Alejandro Barrero wrote:The questions is my statement correct?

That means that the object may be removed from the map at any time but if the application is lucky it may still be there if it is needed again (" it can still get it").


Note that even if the object is NOT still there, the app can still get it if it needs it, by definition of the word "need".
Alejandro Barrero
Ranch Hand

Joined: Aug 01, 2005
Posts: 309
I finally understand the situation. Thank you very much to all.
Jeff Verdegan
Bartender

Joined: Jan 03, 2004
Posts: 6109
    
    6

You're very welcome!
 
wood burning stoves
 
subject: Question on WeakHashMap
 
Similar Threads
A canonicalizing WeakHashMap
WeakHashMap
Data: Mutition/Singletone
Why we have WeakHashMap and not SoftHashMap
Weakhashmap and canonicalized mapping