Edit (Aug. 2012):
It turns out that currently the best solution are probably Guava 13.0’s Cache classes, explained on Guava’s Wiki – that’s what I’m going to use.
It even supports building a SoftHashMap (see CacheBuilder.newBuilder().softKeys()), but it is probably not what you want, as Java expert Jeremy Manson explains (below you’ll find the link).
Not that I know of (Nov. 2008), but you kind find some implementation of SoftHashMap on the net.
Like this one: SoftHashMap or this one.
Edit (Nov. 2009)
As Matthias mentions in the comments, the Google Guava MapMaker does use SoftReferences:
A
ConcurrentMapbuilder, providing any combination of these features:
- soft or weak keys,
- soft or weak values,
- timed expiration, and
- on-demand computation of values.
As mentioned in this thread, another JSR166y candidate:
jsr166y.ConcurrentReferenceHashMap
It provides an alternative concurrent reference map to the Google implementation (which relies on a background thread to evict entries)
Edit (August 2012)
The Google implementation uses a background thread only when timed expiration of entries is requested. In particular, it simply uses java.util.Timer, which is not so intrusive as having a separate background thread.
Jeremy Manson recommends, for any cache, using this feature to avoid the dangers of SoftReference:
http://jeremymanson.blogspot.de/2009/07/how-hotspot-decides-to-clear_07.html
There’s another implementation from Apache Commons, namely org.apache.commons.collections.map.ReferenceMap; it does not support timed removal, but it does support choosing whether keys should be compared by identity or by equality. Moreover, this implementation is not concurrent – it can be made synchronized, but that works less well under accesses from multiple threads.