Garret Wilson
Garret Wilson

Reputation: 21436

Simple thread-safe Java hash map with weak values in Java or Google Guava?

I want to keep a map of singleton objects based on their ID, just to ensure that everyone gets the same copy. The creation of these objects happens seldom, and I don't want or need the overhead of a concurrent map (which will internally keep essentially multiple maps in memory). But I do need the map to support weak keys, so that when nobody is using a particular instance the record will be dropped from the map.

So what choice do I have? Guava MapMaker and CacheBuilder create concurrent maps, which use a lot more memory than I need. I don't need "concurrency" --- I just need thread safety. Yes, I could set the concurrency level to 1, but according to the API documentation this is is only a hint, and may be ignored altogether in the future.

I could use Java Collections to create a simple synchronized HashMap and use putIfAbsent(...), but that doesn't give me the benefit of weak values. I could store weak references, but they wouldn't automatically be expunged on access of the map.

If I had a version of Java's WeakHashMap that supported weak values instead of weak keys, I could wrap it in a synchronized map and be done with it.

I believe that long ago Apache Commons Collections had a map builder that allowed the specification of weak values, but we're using Guava instead.

Any suggestions? And please, read the full question before jumping to throw in a suggestion I've already mentioned.

Upvotes: 2

Views: 545

Answers (2)

maaartinus
maaartinus

Reputation: 46482

I'd say this is a perfect example of misplaced optimization. You're saying you don't need concurrency and you don't want to pay the price for multiple map segments. But each such segment stores only a part of the entries, so the added overhead is no more than some hundreds bytes per segment, or rather less.

You're saying that the stored objects are singletons. This implies that you need only a single such map. Currently, Guava's cache creates the requested number of segments, i.e., one in your case (so the only memory overhead comes from the length one segment array (4 bytes) and some bookkeeping data (similar size). Assuming this should get much worse, and you get 64 segments with concurrencyLevel(1), you'll lose maybe some kilobytes. Unless you're going to run your app on something like ZX Spectrum, it really shouldn't matter.

Maybe I've missed something, maybe you left out something. Feel free to clarify.

Upvotes: 1

c.sankhala
c.sankhala

Reputation: 909

create your own WeakReference and use it in HashMap<key,weakObj> . Hope this might work.

Upvotes: 0

Related Questions