KickJava   Java API By Example, From Geeks To Geeks.

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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