de.mguennewig.pobjects
Class SoftHashMap<K,V>

java.lang.Object
  extended by java.util.AbstractMap<K,V>
      extended by de.mguennewig.pobjects.SoftHashMap<K,V>
All Implemented Interfaces:
java.util.Map<K,V>

public class SoftHashMap<K,V>
extends java.util.AbstractMap<K,V>
implements java.util.Map<K,V>

A hashtable-based Map implementation with soft values.

An entry in a SoftHashMap will automatically be removed when its value is no longer in ordinary use. More precisely, the presence of a mapping for a given value will not prevent the key from being discarded by the garbage collector, that is, made finalizable, finalized, and then reclaimed. When a value has been discarded its entry is effectively removed from the map, so this class behaves somewhat differently than other Map implementations.

Both null values and the null key are supported. This class has performance characteristics similar to those of the HashMap class, and has the same efficiency parameters of initial capacity and load factor.

Like most collection classes, this class is not synchronized. A synchronized SoftHashMap may be constructed using the Collections.synchronizedMap(Map) method.

The behavior of the SoftHashMap class depends in part upon the actions of the garbage collector, so several familiar (though not required) Map invariants do not hold for this class. Because the garbage collector may discard values at any time, a SoftHashMap may behave as though an unknown thread is silently removing entries. In particular, even if you synchronize on a SoftHashMap instance and invoke none of its mutator methods, it is possible for the size() method to return smaller values over time, for the AbstractMap.isEmpty() method to return false and then true, for the containsKey(Object) method to return true and later false for a given key, for the get(Object) method to return a value for a given key but later return null, for the put(Object,Object) method to return null and the remove method to return false for a key that previously appeared to be in the map, and for successive examinations of the key set, the value set, and the entry set to yield successively smaller numbers of elements.

Each value object in a SoftHashMap is stored indirectly as the referent of a soft reference. Therefore a value will automatically be removed only after the soft references to it, both inside and outside of the map, have been cleared by the garbage collector.

Implementation note: The key objects in a SoftHashMap are held by ordinary strong references. Thus care should be taken to ensure that key objects do not strongly refer to their own values, either directly or indirectly, since that will prevent the keys from being discarded. Note that a key object may refer indirectly to its value via the SoftHashMap itself; that is, a key object may strongly refer to some other value object whose associated key object, in turn, strongly refers to the value of the first key object. One way to deal with this is to wrap keys themselves within SoftReferences before inserting, as in: m.put(new SoftReference(key), value), and wrapping upon each get.

The iterators returned by all of this class's "collection view methods" are fail-fast: if the map is structurally modified at any time after the iterator is created, in any way except through the iterator's own Iterator.remove() method, the iterator will throw a ConcurrentModificationException. Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.

Note that the fail-fast behavior of an iterator cannot be guaranteed as it is, generally speaking, impossible to make any hard guarantees in the presence of unsynchronized concurrent modification. Fail-fast iterators throw ConcurrentModificationException on a best-effort basis. Therefore, it would be wrong to write a program that depended on this exception for its correctness: the fail-fast behavior of iterators should be used only to detect bugs.

Author:
Michael Günnewig
See Also:
SoftReference, WeakHashMap

Nested Class Summary
 
Nested classes/interfaces inherited from class java.util.AbstractMap
java.util.AbstractMap.SimpleEntry<K,V>, java.util.AbstractMap.SimpleImmutableEntry<K,V>
 
Constructor Summary
SoftHashMap()
          Creates a new, empty SoftHashMap with the default initial capacity (16) and the default load factor (0.75).
SoftHashMap(int initialCapacity)
          Creates a new, empty SoftHashMap with the given initial capacity and the default load factor, which is 0.75.
SoftHashMap(int initialCapacity, float loadFactor)
          Creates a new, empty SoftHashMap with the given initial capacity and the given load factor.
SoftHashMap(java.util.Map<? extends K,? extends V> t)
          Constructs a new SoftHashMap with the same mappings as the specified Map.
 
Method Summary
 void clear()
          
 boolean containsKey(java.lang.Object key)
          
 java.util.Set<java.util.Map.Entry<K,V>> entrySet()
          
 V get(java.lang.Object key)
          
 java.util.Set<K> keySet()
          
 V put(K key, V value)
          
 void putAll(java.util.Map<? extends K,? extends V> m)
          
 V remove(java.lang.Object key)
          
 int size()
          
 java.util.Collection<V> values()
          
 
Methods inherited from class java.util.AbstractMap
containsValue, equals, hashCode, isEmpty, toString
 
Methods inherited from class java.lang.Object
getClass, notify, notifyAll, wait, wait, wait
 
Methods inherited from interface java.util.Map
containsValue, equals, hashCode, isEmpty
 

Constructor Detail

SoftHashMap

public SoftHashMap()
Creates a new, empty SoftHashMap with the default initial capacity (16) and the default load factor (0.75).


SoftHashMap

public SoftHashMap(int initialCapacity)
Creates a new, empty SoftHashMap with the given initial capacity and the default load factor, which is 0.75.

Throws:
java.lang.IllegalArgumentException - if the initial capacity is negative.

SoftHashMap

public SoftHashMap(int initialCapacity,
                   float loadFactor)
Creates a new, empty SoftHashMap with the given initial capacity and the given load factor.

Throws:
java.lang.IllegalArgumentException - if the initial capacity is negative or the load factor is non-positive.

SoftHashMap

public SoftHashMap(java.util.Map<? extends K,? extends V> t)
Constructs a new SoftHashMap with the same mappings as the specified Map.

Method Detail

clear

public void clear()

Specified by:
clear in interface java.util.Map<K,V>
Overrides:
clear in class java.util.AbstractMap<K,V>

containsKey

public boolean containsKey(java.lang.Object key)

Specified by:
containsKey in interface java.util.Map<K,V>
Overrides:
containsKey in class java.util.AbstractMap<K,V>

entrySet

public java.util.Set<java.util.Map.Entry<K,V>> entrySet()

Specified by:
entrySet in interface java.util.Map<K,V>
Specified by:
entrySet in class java.util.AbstractMap<K,V>

get

public V get(java.lang.Object key)

Specified by:
get in interface java.util.Map<K,V>
Overrides:
get in class java.util.AbstractMap<K,V>

keySet

public java.util.Set<K> keySet()

Specified by:
keySet in interface java.util.Map<K,V>
Overrides:
keySet in class java.util.AbstractMap<K,V>

put

public V put(K key,
             V value)

Specified by:
put in interface java.util.Map<K,V>
Overrides:
put in class java.util.AbstractMap<K,V>

putAll

public void putAll(java.util.Map<? extends K,? extends V> m)

Specified by:
putAll in interface java.util.Map<K,V>
Overrides:
putAll in class java.util.AbstractMap<K,V>

remove

public V remove(java.lang.Object key)

Specified by:
remove in interface java.util.Map<K,V>
Overrides:
remove in class java.util.AbstractMap<K,V>

size

public int size()

Specified by:
size in interface java.util.Map<K,V>
Overrides:
size in class java.util.AbstractMap<K,V>

values

public java.util.Collection<V> values()

Specified by:
values in interface java.util.Map<K,V>
Overrides:
values in class java.util.AbstractMap<K,V>