2

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.

10
  • 1
    What part of the API documentation are you referring to with "only a hint"? Besides -- at this point, it answers your question, it's only possibly less efficient than you need. Commented Jun 21, 2014 at 17:24
  • Clarification: How will you be determining that no one is using one of your map elements (are you requiring "obtain"/"release" calls using the ID ? Commented Jun 21, 2014 at 17:56
  • @ErstwhileIII, I used the phrase "using a particular instance" colloquially to mean "has a reference to a particular instance". Commented Jun 21, 2014 at 18:10
  • 1
    @SergeBallesta, I would love to use a well-known cache implementation, if one meets the criteria I am looking for. If you know know of a well-known cache implementation that meets the criteria I mentioned, please name it. In fact... um, that was the question! Commented Jun 21, 2014 at 18:41
  • 2
    "More advanced concurrency controls" suggests that things will get better, not worse. Commented Jun 22, 2014 at 17:02

2 Answers 2

1

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.

0

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.