KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > util > collection > WeakValueHashMap


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

22 package org.jboss.util.collection;
23
24 import java.util.Map JavaDoc;
25 import java.util.AbstractMap JavaDoc;
26 import java.util.HashMap JavaDoc;
27 import java.util.Set JavaDoc;
28
29 import java.lang.ref.WeakReference JavaDoc;
30 import java.lang.ref.ReferenceQueue JavaDoc;
31
32
33 /**
34  * This Map will remove entries when the value in the map has been
35  * cleaned from garbage collection
36  *
37  * @version <tt>$Revision: 1958 $</tt>
38  * @author <a HREF="mailto:bill@jboss.org">Bill Burke</a>
39  */

40 public class WeakValueHashMap
41    extends AbstractMap JavaDoc
42    implements Map JavaDoc
43 {
44    private static class WeakValueRef extends WeakReference JavaDoc
45    {
46       public Object JavaDoc key;
47
48       private WeakValueRef(Object JavaDoc key, Object JavaDoc val, ReferenceQueue JavaDoc q)
49       {
50          super(val, q);
51          this.key = key;
52       }
53       
54       private static WeakValueRef create(Object JavaDoc key, Object JavaDoc val, ReferenceQueue JavaDoc q)
55       {
56          if (val == null) return null;
57          else return new WeakValueRef(key, val, q);
58       }
59       
60    }
61    public Set JavaDoc entrySet()
62    {
63       processQueue();
64       return hash.entrySet();
65    }
66
67    /* Hash table mapping WeakKeys to values */
68    private Map JavaDoc hash;
69
70    /* Reference queue for cleared WeakKeys */
71    private ReferenceQueue JavaDoc queue = new ReferenceQueue JavaDoc();
72    
73    /* Remove all invalidated entries from the map, that is, remove all entries
74       whose values have been discarded.
75     */

76    private void processQueue()
77    {
78       WeakValueRef ref;
79       while ((ref = (WeakValueRef)queue.poll()) != null) {
80          if (ref == (WeakValueRef) hash.get(ref.key)) {
81             // only remove if it is the *exact* same WeakValueRef
82
//
83
hash.remove(ref.key);
84          }
85       }
86    }
87
88
89    /* -- Constructors -- */
90
91    /**
92     * Constructs a new, empty <code>WeakHashMap</code> with the given
93     * initial capacity and the given load factor.
94     *
95     * @param initialCapacity The initial capacity of the
96     * <code>WeakHashMap</code>
97     *
98     * @param loadFactor The load factor of the <code>WeakHashMap</code>
99     *
100     * @throws IllegalArgumentException If the initial capacity is less than
101     * zero, or if the load factor is
102     * nonpositive
103     */

104    public WeakValueHashMap(int initialCapacity, float loadFactor)
105    {
106       hash = new HashMap JavaDoc(initialCapacity, loadFactor);
107    }
108
109    /**
110     * Constructs a new, empty <code>WeakHashMap</code> with the given
111     * initial capacity and the default load factor, which is
112     * <code>0.75</code>.
113     *
114     * @param initialCapacity The initial capacity of the
115     * <code>WeakHashMap</code>
116     *
117     * @throws IllegalArgumentException If the initial capacity is less than
118     * zero
119     */

120    public WeakValueHashMap(int initialCapacity)
121    {
122       hash = new HashMap JavaDoc(initialCapacity);
123    }
124
125    /**
126     * Constructs a new, empty <code>WeakHashMap</code> with the default
127     * initial capacity and the default load factor, which is
128     * <code>0.75</code>.
129     */

130    public WeakValueHashMap()
131    {
132       hash = new HashMap JavaDoc();
133    }
134
135    /**
136     * Constructs a new <code>WeakHashMap</code> with the same mappings as the
137     * specified <tt>Map</tt>. The <code>WeakHashMap</code> is created with an
138     * initial capacity of twice the number of mappings in the specified map
139     * or 11 (whichever is greater), and a default load factor, which is
140     * <tt>0.75</tt>.
141     *
142     * @param t the map whose mappings are to be placed in this map.
143     * @since 1.3
144     */

145    public WeakValueHashMap(Map JavaDoc t)
146    {
147       this(Math.max(2*t.size(), 11), 0.75f);
148       putAll(t);
149    }
150
151    /* -- Simple queries -- */
152
153    /**
154     * Returns the number of key-value mappings in this map.
155     * <strong>Note:</strong> <em>In contrast with most implementations of the
156     * <code>Map</code> interface, the time required by this operation is
157     * linear in the size of the map.</em>
158     */

159    public int size()
160    {
161       processQueue();
162       return hash.size();
163    }
164
165    /**
166     * Returns <code>true</code> if this map contains no key-value mappings.
167     */

168    public boolean isEmpty()
169    {
170       processQueue();
171       return hash.isEmpty();
172    }
173
174    /**
175     * Returns <code>true</code> if this map contains a mapping for the
176     * specified key.
177     *
178     * @param key The key whose presence in this map is to be tested
179     */

180    public boolean containsKey(Object JavaDoc key)
181    {
182       processQueue();
183       return hash.containsKey(key);
184    }
185
186    /* -- Lookup and modification operations -- */
187
188    /**
189     * Returns the value to which this map maps the specified <code>key</code>.
190     * If this map does not contain a value for this key, then return
191     * <code>null</code>.
192     *
193     * @param key The key whose associated value, if any, is to be returned
194     */

195    public Object JavaDoc get(Object JavaDoc key)
196    {
197       processQueue();
198       WeakReference JavaDoc ref = (WeakReference JavaDoc)hash.get(key);
199       if (ref != null) return ref.get();
200       return null;
201    }
202
203    /**
204     * Updates this map so that the given <code>key</code> maps to the given
205     * <code>value</code>. If the map previously contained a mapping for
206     * <code>key</code> then that mapping is replaced and the previous value is
207     * returned.
208     *
209     * @param key The key that is to be mapped to the given
210     * <code>value</code>
211     * @param value The value to which the given <code>key</code> is to be
212     * mapped
213     *
214     * @return The previous value to which this key was mapped, or
215     * <code>null</code> if if there was no mapping for the key
216     */

217    public Object JavaDoc put(Object JavaDoc key, Object JavaDoc value)
218    {
219       processQueue();
220       Object JavaDoc rtn = hash.put(key, WeakValueRef.create(key, value, queue));
221       if (rtn != null) rtn = ((WeakReference JavaDoc)rtn).get();
222       return rtn;
223    }
224
225    /**
226     * Removes the mapping for the given <code>key</code> from this map, if
227     * present.
228     *
229     * @param key The key whose mapping is to be removed
230     *
231     * @return The value to which this key was mapped, or <code>null</code> if
232     * there was no mapping for the key
233     */

234    public Object JavaDoc remove(Object JavaDoc key)
235    {
236       processQueue();
237       return hash.remove(key);
238    }
239
240    /**
241     * Removes all mappings from this map.
242     */

243    public void clear()
244    {
245       processQueue();
246       hash.clear();
247    }
248 }
249
Popular Tags