com.h3c.util.cache

## Class WeakValueCache<K,V>

- java.lang.Object
- - com.h3c.util.cache.WeakValueCache<K,V>

- Type Parameters:
    `K` - the type of keys maintained by this map
    `V` - the type of mapped values

      public final class WeakValueCache<K,V>
      extends Object

  Implements a cache (map) that allows its values to be garbage collected when all external references to the values have been dropped.

  Note that this class intentionally does not implement the full `Map` interface; It only provides `get(K)`, `put(K, V)` and `size()` methods.

  When an instance of `WeakValueCache` is constructed, it requires a `ReferenceQueue` as a parameter. That queue is where the "zombie" `references` will be placed when values are garbage collected. It is expected that a `CacheCleaner` is "attached" to the queue to automatically remove entries containing zombie references from the internal map.

  These classes were designed this way to allow a common reference queue to be used for related data types, and thus have one common background thread do clean up for a number of caches, rather than one thread per cache.

  The recommended usage pattern for these classes is as follows:

  Suppose you have 3 datatypes: `Type1`, `Type2`, `Type3`, for which you want caches. Also suppose they all extend `SuperType`. The `SuperType` class is a good place to define the common reference queue with attached `CacheCleaner`:

       public abstract class SuperType {
           // lazily initialized reference queue
           private static ReferenceQueue<SuperType> refQ;

           // allow subclasses to retrieve a reference to the queue
           // first invocation creates and starts the cleaner thread
           protected static synchronized ReferenceQueue<SuperType> getRefQ() {
               if (refQ == null) {
                   refQ = new ReferenceQueue<SuperType>();
                   new CacheCleaner(refQ).start();
               }
               return refQ;
           }
       }

  The datatype classes will look something like this:

       public final class Type1 extends SuperType {
           // private constructor(s) to control instance creation
           private Type1(final String str) {
               ...
           }

           ...

           // our self-trimming cache
           private static final WeakValueCache<String, Type1> cache =
                            new WeakValueCache<String, Type1>(getRefQ());
           ...

           // PUBLIC API:
           public static Type1 valueOf(final String stringRep) {
               synchronized (cache) {
                   Type1 t = cache.get(stringRep);
                   if (t == null) {
                       t = new Type1(stringRep);
                       cache.put(stringRep, t);
                   }
                   return t;
               } // sync
           }
       }

  Note the synchronization on the cache object in the `valueOf` method. This is necessary to make the "find or create" paradigm "atomic" with respect to the cache. The `CacheCleaner` also synchronizes on the cache during its work of removing zombie entries.

- - ### Constructor Summary

    Constructors
    Constructor and Description
    `WeakValueCache(ReferenceQueue<? super V> queue)` Constructs an empty weak value map with the specified reference queue for GC'd value reference housekeeping.

  - ### Method Summary

    Methods
    Modifier and Type | Method and Description
    --- | ---
    `V` | `get(K key)` Returns the value to which the specified key is mapped, or `null` if this map contains no mapping for the key.
    `V` | `put(K key, V value)` Associates the specified value with the specified key in this map.
    `int` | `size()` Returns the size of the map.

    - ### Methods inherited from class java.lang.Object

      `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- - ### Constructor Detail

    - #### WeakValueCache

          public WeakValueCache(ReferenceQueue<? super V> queue)

      Constructs an empty weak value map with the specified reference queue for GC'd value reference housekeeping.
      Parameters:
        `queue` - the reference queue
      Throws:
        `NullPointerException` - if queue is null

  - ### Method Detail

    - #### get

          public V get(K key)

      Returns the value to which the specified key is mapped, or `null` if this map contains no mapping for the key.
      Parameters:
        `key` - the key
      Returns:
        the value mapped to that key, or null
      Throws:
        `NullPointerException` - if key is null

    - #### put

          public V put(K key,
              V value)

      Associates the specified value with the specified key in this map. If the map previously contained a mapping for the key, the old value is replaced.
      Parameters:
        `key` - the key with which the specified value is to be associated
        `value` - the value to be associated with the specified key
      Returns:
        the previous value associated with `key`, or `null` if there was no mapping for `key`.
      Throws:
        `NullPointerException` - if key or value is null

    - #### size

          public int size()

      Returns the size of the map. Note that GC'd-but-not-yet-cleaned-up entries are included in the count, so the "actual" number of values remaining in the cache may be smaller than the value reported here.
      Returns:
        the number of entries in the map

Copyright © 2014. All Rights Reserved.