An implementation of Set that manages a map of soft references to the set values. : SoftReference « Collections Data Structure « Java






An implementation of Set that manages a map of soft references to the set values.

   
 
/*
 * JBoss, Home of Professional Open Source
 * Copyright 2005, JBoss Inc., and individual contributors as indicated
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */

import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.reflect.Array;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;

/**
 * An implementation of Set that manages a map of soft references to the set
 * values. The map is keyed by the value hashCode and so this is only useful for
 * value whose hashCode is a valid identity representation (String, primative
 * wrappers, etc).
 * 
 * @author Scott.Stark@jboss.org
 * @version $Revision: 2787 $
 */
@SuppressWarnings("unchecked")
public class SoftSet implements Set {
  private HashMap map = new HashMap();

  /** The queue of garbage collected soft references */
  private ReferenceQueue gcqueue = new ReferenceQueue();

  static class ComparableSoftReference extends SoftReference {
    private Integer key;

    ComparableSoftReference(Integer key, Object o, ReferenceQueue q) {
      super(o, q);
      this.key = key;
    }

    Integer getKey() {
      return key;
    }
  }

  static class ComparableSoftReferenceIterator implements Iterator {
    Iterator theIter;

    ComparableSoftReferenceIterator(Iterator theIter) {
      this.theIter = theIter;
    }

    public boolean hasNext() {
      return theIter.hasNext();
    }

    public Object next() {
      ComparableSoftReference csr = (ComparableSoftReference) theIter.next();
      return csr.get();
    }

    public void remove() {
      theIter.remove();
    }
  }

  /**
   * 
   */
  public SoftSet() {
  }

  public int size() {
    processQueue();
    return map.size();
  }

  public boolean isEmpty() {
    processQueue();
    return map.isEmpty();
  }

  public boolean contains(Object o) {
    processQueue();
    Integer key = new Integer(o.hashCode());
    boolean contains = map.containsKey(key);
    return contains;
  }

  public Iterator iterator() {
    processQueue();
    Iterator theIter = map.values().iterator();
    return new ComparableSoftReferenceIterator(theIter);
  }

  public Object[] toArray() {
    processQueue();
    return toArray(new Object[0]);
  }

  public Object[] toArray(Object[] a) {
    processQueue();
    int size = map.size();
    Object[] array = {};
    if (a.length >= size)
      array = a;
    Iterator iter = map.values().iterator();
    int index = 0;
    while (iter.hasNext()) {
      ComparableSoftReference csr = (ComparableSoftReference) iter.next();
      Object value = csr.get();
      // Create the correct array type
      if (array.length == 0) {
        if (value == null) {
          index++;
          continue;
        }
        Array.newInstance(value.getClass(), size);
      }
      array[index] = value;
      index++;
    }
    return array;
  }

  public boolean add(Object o) {
    processQueue();
    Integer key = new Integer(o.hashCode());
    ComparableSoftReference sr = new ComparableSoftReference(key, o, gcqueue);
    return map.put(key, sr) == null;
  }

  public boolean remove(Object o) {
    processQueue();
    Integer key = new Integer(o.hashCode());
    return map.remove(key) != null;
  }

  public boolean containsAll(Collection c) {
    processQueue();
    Iterator iter = c.iterator();
    boolean contains = true;
    while (iter.hasNext()) {
      Object value = iter.next();
      Integer key = new Integer(value.hashCode());
      contains &= map.containsKey(key);
    }
    return contains;
  }

  public boolean addAll(Collection c) {
    processQueue();
    Iterator iter = c.iterator();
    boolean added = false;
    while (iter.hasNext()) {
      Object value = iter.next();
      Integer key = new Integer(value.hashCode());
      ComparableSoftReference sr = new ComparableSoftReference(key, value, gcqueue);
      added |= map.put(key, sr) == null;
    }
    return added;
  }

  public boolean retainAll(Collection c) {
    Iterator iter = iterator();
    boolean removed = false;
    while (iter.hasNext()) {
      Object value = iter.next();
      if (c.contains(value) == false) {
        iter.remove();
        removed = true;
      }
    }
    return removed;
  }

  public boolean removeAll(Collection c) {
    processQueue();
    Iterator iter = c.iterator();
    boolean removed = false;
    while (iter.hasNext()) {
      Object value = iter.next();
      removed |= remove(value);
    }
    return removed;
  }

  public void clear() {
    while (gcqueue.poll() != null)
      ;
    map.clear();
  }

  public boolean equals(Object o) {
    return map.equals(o);
  }

  public int hashCode() {
    return map.hashCode();
  }

  /**
   * Iterate through the gcqueue for for any cleared reference, remove the
   * associated value from the underlying set.
   */
  private void processQueue() {
    ComparableSoftReference cr;
    while ((cr = (ComparableSoftReference) gcqueue.poll()) != null) {
      map.remove(cr.getKey());
    }
  }

}

   
    
    
  








Related examples in the same category

1.A soft reference holds onto its referent until memory becomes low.
2.A weak reference is used to determine when an object is no longer being referenced.
3.A phantom reference is used to determine when an object is just about to be reclaimed.
4.Testing SoftReference
5.Testing WeakReference
6.Testing PhantomReference
7.Soft ValueMap
8.Cache based on SoftReference