Solution 1:

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 ConcurrentMap builder, 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.

Solution 2:

I am familiar with two libraries that offer a SoftHashMap implementation:

  1. Apache Commons: org.apache.commons.collections.map.ReferenceMap

  2. Google Collections: com.google.common.collect.ReferenceMap