Hi!
Thank you for your ideas. I'd like to summarize it in one mail.
Iterating over keySet is what I meant with "obvious brute force
attack". The map is expected to have quite a lot of entries (could
easily eat up a quarter of all available VM heap memory or so). In
fact, this brute force attack currently used, but of course I want to
have an alternative way.
A separate hashmap is not what I want. Then I have two of such big maps
in memory instead of just one. That hit counter is a small
nice-to-have, which does not justify any significant additional memory
footprint or cpu usage.
Wrapping values into another class is also not an option for the same
reason. This would require one additional object instance for each
cache entry - too expensive for me.
Design - Yes I know, that an equals-method (and hashCode), that does
not cover all member fields of the class (it omits field hits in my
example) is not a nice design. However, all this is deeply buried
within the core of the framework. Neither class Key nor Cache is
publicly visible.
Memory Usage is quite important for me. The map is for caching database
queries across transactions. All objects in the map are there for a
long time, which moves them sooner or later into the old-gen space,
which is subject to expensive full-GCs.
Until recently I solved the problem using commons-collections. The maps
of commons-collections do provide a protected method getEntry(Object
key). Within a subclass I can implement getKey(Object key) with
getEntry(key).getKey(). Java Collections do have that getEntry method
as well, but this is package private, so I cannot access is via
subclassing.
While writing this mail I thought about calling getEntry via
reflection, bypassing the package-private-restriction. Really ugly...
Thank you for responses,
Ralf.