KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > aop > util > SoftValueHashMap


1 /***************************************
2  * *
3  * JBoss: The OpenSource J2EE WebOS *
4  * *
5  * Distributable under LGPL license. *
6  * See terms of license at gnu.org. *
7  * *
8  ***************************************/

9
10 package org.jboss.aop.util;
11
12 import java.lang.ref.ReferenceQueue JavaDoc;
13 import java.lang.ref.SoftReference JavaDoc;
14 import java.util.AbstractMap JavaDoc;
15 import java.util.HashMap JavaDoc;
16 import java.util.Map JavaDoc;
17 import java.util.Set JavaDoc;
18
19
20 /**
21  * This Map will remove entries when the value in the map has been
22  * cleaned from garbage collection
23  *
24  * @version <tt>$Revision: 1.1 $</tt>
25  * @author <a HREF="mailto:bill@jboss.org">Bill Burke</a>
26  */

27 public class SoftValueHashMap
28    extends AbstractMap JavaDoc
29    implements Map JavaDoc
30 {
31    private static class SoftValueRef extends SoftReference JavaDoc
32    {
33       public Object JavaDoc key;
34
35       private SoftValueRef(Object JavaDoc key, Object JavaDoc val, ReferenceQueue JavaDoc q)
36       {
37          super(val, q);
38          this.key = key;
39       }
40       
41       private static SoftValueRef create(Object JavaDoc key, Object JavaDoc val, ReferenceQueue JavaDoc q)
42       {
43          if (val == null) return null;
44          else return new SoftValueRef(key, val, q);
45       }
46       
47    }
48    public Set JavaDoc entrySet()
49    {
50       processQueue();
51       return hash.entrySet();
52    }
53
54    /* Hash table mapping WeakKeys to values */
55    private Map JavaDoc hash;
56
57    /* Reference queue for cleared WeakKeys */
58    private ReferenceQueue JavaDoc queue = new ReferenceQueue JavaDoc();
59    
60    /* Remove all invalidated entries from the map, that is, remove all entries
61       whose values have been discarded.
62     */

63    private void processQueue()
64    {
65       SoftValueRef ref;
66       while ((ref = (SoftValueRef)queue.poll()) != null) {
67          if (ref == (SoftValueRef) hash.get(ref.key)) {
68             // only remove if it is the *exact* same WeakValueRef
69
//
70
hash.remove(ref.key);
71          }
72       }
73    }
74
75
76    /* -- Constructors -- */
77
78    /**
79     * Constructs a new, empty <code>WeakHashMap</code> with the given
80     * initial capacity and the given load factor.
81     *
82     * @param initialCapacity The initial capacity of the
83     * <code>WeakHashMap</code>
84     *
85     * @param loadFactor The load factor of the <code>WeakHashMap</code>
86     *
87     * @throws IllegalArgumentException If the initial capacity is less than
88     * zero, or if the load factor is
89     * nonpositive
90     */

91    public SoftValueHashMap(int initialCapacity, float loadFactor)
92    {
93       hash = new HashMap JavaDoc(initialCapacity, loadFactor);
94    }
95
96    /**
97     * Constructs a new, empty <code>WeakHashMap</code> with the given
98     * initial capacity and the default load factor, which is
99     * <code>0.75</code>.
100     *
101     * @param initialCapacity The initial capacity of the
102     * <code>WeakHashMap</code>
103     *
104     * @throws IllegalArgumentException If the initial capacity is less than
105     * zero
106     */

107    public SoftValueHashMap(int initialCapacity)
108    {
109       hash = new HashMap JavaDoc(initialCapacity);
110    }
111
112    /**
113     * Constructs a new, empty <code>WeakHashMap</code> with the default
114     * initial capacity and the default load factor, which is
115     * <code>0.75</code>.
116     */

117    public SoftValueHashMap()
118    {
119       hash = new HashMap JavaDoc();
120    }
121
122    /**
123     * Constructs a new <code>WeakHashMap</code> with the same mappings as the
124     * specified <tt>Map</tt>. The <code>WeakHashMap</code> is created with an
125     * initial capacity of twice the number of mappings in the specified map
126     * or 11 (whichever is greater), and a default load factor, which is
127     * <tt>0.75</tt>.
128     *
129     * @param t the map whose mappings are to be placed in this map.
130     * @since 1.3
131     */

132    public SoftValueHashMap(Map JavaDoc t)
133    {
134       this(Math.max(2*t.size(), 11), 0.75f);
135       putAll(t);
136    }
137
138    /* -- Simple queries -- */
139
140    /**
141     * Returns the number of key-value mappings in this map.
142     * <strong>Note:</strong> <em>In contrast with most implementations of the
143     * <code>Map</code> interface, the time required by this operation is
144     * linear in the size of the map.</em>
145     */

146    public int size()
147    {
148       processQueue();
149       return hash.size();
150    }
151
152    /**
153     * Returns <code>true</code> if this map contains no key-value mappings.
154     */

155    public boolean isEmpty()
156    {
157       processQueue();
158       return hash.isEmpty();
159    }
160
161    /**
162     * Returns <code>true</code> if this map contains a mapping for the
163     * specified key.
164     *
165     * @param key The key whose presence in this map is to be tested
166     */

167    public boolean containsKey(Object JavaDoc key)
168    {
169       processQueue();
170       return hash.containsKey(key);
171    }
172
173    /* -- Lookup and modification operations -- */
174
175    /**
176     * Returns the value to which this map maps the specified <code>key</code>.
177     * If this map does not contain a value for this key, then return
178     * <code>null</code>.
179     *
180     * @param key The key whose associated value, if any, is to be returned
181     */

182    public Object JavaDoc get(Object JavaDoc key)
183    {
184       processQueue();
185       SoftReference JavaDoc ref = (SoftReference JavaDoc)hash.get(key);
186       if (ref != null) return ref.get();
187       return null;
188    }
189
190    /**
191     * Updates this map so that the given <code>key</code> maps to the given
192     * <code>value</code>. If the map previously contained a mapping for
193     * <code>key</code> then that mapping is replaced and the previous value is
194     * returned.
195     *
196     * @param key The key that is to be mapped to the given
197     * <code>value</code>
198     * @param value The value to which the given <code>key</code> is to be
199     * mapped
200     *
201     * @return The previous value to which this key was mapped, or
202     * <code>null</code> if if there was no mapping for the key
203     */

204    public Object JavaDoc put(Object JavaDoc key, Object JavaDoc value)
205    {
206       processQueue();
207       Object JavaDoc rtn = hash.put(key, SoftValueRef.create(key, value, queue));
208       if (rtn != null) rtn = ((SoftReference JavaDoc)rtn).get();
209       return rtn;
210    }
211
212    /**
213     * Removes the mapping for the given <code>key</code> from this map, if
214     * present.
215     *
216     * @param key The key whose mapping is to be removed
217     *
218     * @return The value to which this key was mapped, or <code>null</code> if
219     * there was no mapping for the key
220     */

221    public Object JavaDoc remove(Object JavaDoc key)
222    {
223       processQueue();
224       return hash.remove(key);
225    }
226
227    /**
228     * Removes all mappings from this map.
229     */

230    public void clear()
231    {
232       processQueue();
233       hash.clear();
234    }
235 }
236
Popular Tags