CleaningWeakReferenceMap.java

  1. /**
  2.  *
  3.  * Copyright the original author or authors
  4.  *
  5.  * Licensed under the Apache License, Version 2.0 (the "License");
  6.  * you may not use this file except in compliance with the License.
  7.  * You may obtain a copy of the License at
  8.  *
  9.  *     http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.jivesoftware.smack.util;

  18. import java.lang.ref.WeakReference;
  19. import java.util.HashMap;
  20. import java.util.Iterator;

  21. /**
  22.  * Extends a {@link HashMap} with {@link WeakReference} values, so that
  23.  * weak references which have been cleared are periodically removed from
  24.  * the map. The cleaning occurs as part of {@link #put}, after a specific
  25.  * number ({@link #cleanInterval}) of calls to {@link #put}.
  26.  *
  27.  * @param <K> The key type.
  28.  * @param <V> The value type.
  29.  *
  30.  * @author Boris Grozev
  31.  */
  32. public class CleaningWeakReferenceMap<K, V>
  33.     extends HashMap<K, WeakReference<V>> {
  34.     private static final long serialVersionUID = 0L;

  35.     /**
  36.      * The number of calls to {@link #put} after which to clean this map
  37.      * (i.e. remove cleared {@link WeakReference}s from it).
  38.      */
  39.     private final int cleanInterval;

  40.     /**
  41.      * The number of times {@link #put} has been called on this instance
  42.      * since the last time it was {@link #clean}ed.
  43.      */
  44.     private int numberOfInsertsSinceLastClean = 0;

  45.     /**
  46.      * Initializes a new {@link CleaningWeakReferenceMap} instance with the
  47.      * default clean interval.
  48.      */
  49.     public CleaningWeakReferenceMap() {
  50.         this(50);
  51.     }

  52.     /**
  53.      * Initializes a new {@link CleaningWeakReferenceMap} instance with a given
  54.      * clean interval.
  55.      * @param cleanInterval the number of calls to {@link #put} after which the
  56.      * map will clean itself.
  57.      */
  58.     public CleaningWeakReferenceMap(int cleanInterval) {
  59.         this.cleanInterval = cleanInterval;
  60.     }

  61.     @Override
  62.     public WeakReference<V> put(K key, WeakReference<V> value) {
  63.         WeakReference<V> ret = super.put(key, value);

  64.         if (numberOfInsertsSinceLastClean++ > cleanInterval) {
  65.             numberOfInsertsSinceLastClean = 0;
  66.             clean();
  67.         }

  68.         return ret;
  69.     }

  70.     /**
  71.      * Removes all cleared entries from this map (i.e. entries whose value
  72.      * is a cleared {@link WeakReference}).
  73.      */
  74.     private void clean() {
  75.         Iterator<Entry<K, WeakReference<V>>> iter = entrySet().iterator();
  76.         while (iter.hasNext()) {
  77.             Entry<K, WeakReference<V>> e = iter.next();
  78.             if (e != null && e.getValue() != null
  79.                 && e.getValue().get() == null) {
  80.                 iter.remove();
  81.             }
  82.         }
  83.     }
  84. }