Collections Data Structure Java

/*
 * Copyright 2002-2006 (C) TJDO.
 * All rights reserved.
 *
 * This software is distributed under the terms of the TJDO License version 1.0.
 * See the terms of the TJDO License in the documentation provided with this software.
 *
 * $Id: WeakValueMap.java,v 1.5 2006/09/08 16:11:28 jackknifebarber Exp $
 */
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.AbstractMap;
import java.util.AbstractSet;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
 * A java.util.Map implementation with weak values.
 * 


 * The values are stored in the map as weak references.
 * If the garbage collector clears the reference, the corresponding key is
 * automatically removed from the map.
 *
 * @author Mike Martin
 * @version $Revision: 1.5 $
 *
 * @see WeakReference
 */
public class WeakValueMap extends ReferenceValueMap
{
    public WeakValueMap()
    {
        super(new HashMap());
    }
    public WeakValueMap(int initialCapacity)
    {
        super(new HashMap(initialCapacity));
    }
    public WeakValueMap(int initialCapacity, float loadFactor)
    {
        super(new HashMap(initialCapacity, loadFactor));
    }
    public WeakValueMap(Map m)
    {
        super(new HashMap(m));
    }
    protected Reference newReference(Object value)
    {
        return new WeakReference(value, refQueue);
    }
}
/**
 * A java.util.Map implementation using reference values.
 * 


 * The values are stored in the map as references.
 * If the garbage collector clears the reference, the corresponding key is
 * automatically removed from the map.
 *
 * @author  Mike Martin
 * @version $Revision: 1.8 $
 */
abstract class ReferenceValueMap extends AbstractMap
{
    protected final ReferenceQueue refQueue = new ReferenceQueue();
    /** Backing map. */
    private final Map backing;
    ReferenceValueMap(Map backing)
    {
        this.backing = backing;
    }
    /**
     * Returns a new Reference object to be inserted into the map.
     * Subclasses must implement this method to construct Reference
     * objects of the desired type (e.g. SoftReference, etc.).
     *
     * @param value
     *      The associated value to be referenced.
     *
     * @return
     *      A new Reference object to be inserted into the map.
     */
    protected abstract Reference newReference(Object value);
    private void reap()
    {
        Reference ref;
        while ((ref = refQueue.poll()) != null)
            backing.values().remove(ref);
    }
    public Object put(Object key, Object value)
    {
        reap();
        return backing.put(key, newReference(value));
    }
    public Object get(Object key)
    {
        reap();
        Object v = backing.get(key);
        return (v instanceof Reference) ? ((Reference)v).get() : v;
    }
    public int size()
    {
        reap();
        return backing.size();
    }
    public boolean isEmpty()
    {
        reap();
        return backing.isEmpty();
    }
    public boolean containsKey(Object key)
    {
        reap();
        return backing.containsKey(key);
    }
    public boolean containsValue(Object value)
    {
        reap();
        return super.containsValue(value);
    }
    public Set keySet()
    {
        reap();
        return backing.keySet();
    }
    public Collection values()
    {
        reap();
        return super.values();
    }
    public Set entrySet()
    {
        reap();
        return new EntrySet();
    }
    public Object remove(Object key)
    {
        reap();
        return backing.remove(key);
    }
    public int hashCode()
    {
        reap();
        return super.hashCode();
    }
    public boolean equals(Object o)
    {
        reap();
        return super.equals(o);
    }
    public String toString()
    {
        reap();
        return super.toString();
    }
    static boolean eq(Object o1, Object o2)
    {
        return o1 == null ? o2 == null : o1.equals(o2);
    }
    private class EntrySet extends AbstractSet
    {
        /** Backing set. */
        private final Set set = backing.entrySet();
        public Iterator iterator()
        {
            return new Iterator()
            {
                private Iterator i = set.iterator();
                public boolean hasNext()
                {
                    return i.hasNext();
                }
                public void remove()
                {
                    i.remove();
                }
                public Object next()
                {
                    final Map.Entry ent = (Map.Entry)i.next();
                    return new Map.Entry()
                    {
                        public Object getKey()
                        {
                            return ent.getKey();
                        }
                        public Object getValue()
                        {
                            Object v = ent.getValue();
                            return (v instanceof Reference) ? ((Reference)v).get() : v;
                        }
                        public Object setValue(Object v)
                        {
                            Object oldVal = getValue();
                            ent.setValue(newReference(v));
                            return oldVal;
                        }
                        public boolean equals(Object o)
                        {
                            if (o == this)
                                return true;
                            if (!(o instanceof Map.Entry))
                                return false;
                            Map.Entry e = (Map.Entry)o;
                            return eq(ent.getKey(), e.getKey())
                                && eq(ent.getValue(), e.getValue());
                        }
                        public int hashCode()
                        {
                            Object key = ent.getKey();
                            Object val = ent.getValue();
                            return (key == null ? 0 : key.hashCode())
                                 ^ (val == null ? 0 : val.hashCode());
                        }
                        public String toString()
                        {
                            return ent.getKey() + "=" + ent.getValue();
                        }
                    };
                }
            };
        }
        public int size()
        {
            reap();
            return set.size();
        }
        public boolean isEmpty()
        {
            reap();
            return set.isEmpty();
        }
        public boolean contains(Object o)
        {
            reap();
            return super.contains(o);
        }
        public Object[] toArray()
        {
            reap();
            return super.toArray();
        }
        public Object[] toArray(Object[] a)
        {
            reap();
            return super.toArray(a);
        }
        public boolean remove(Object o)
        {
            reap();
            return super.remove(o);
        }
        public boolean containsAll(Collection c)
        {
            reap();
            return super.containsAll(c);
        }
        public boolean removeAll(Collection c)
        {
            reap();
            return super.removeAll(c);
        }
        public boolean retainAll(Collection c)
        {
            reap();
            return super.retainAll(c);
        }
        public void clear()
        {
            set.clear();
        }
        public String toString()
        {
            reap();
            return super.toString();
        }
    }
}