Mega Code Archive

 
Categories / Java Tutorial / Collections
 

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());     }   } }