KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > enhydra > barracuda > plankton > data > SoftHashMap


1 /*
2  * ---------------------------------------------------------------------
3  * This class is taken verbatim from a free implementation which is described
4  * and documented here: http://archive.devx.com/java/free/articles/Kabutz01/Kabutz01-1.asp.
5  * You may also wish to visit the author's website here: http://www.javaspecialists.co.za
6  *
7  * The only modification made has been to change the package for easy inclusion
8  * in Barracuda's Plankton library, and to include the EPL licensing verbiage
9  * ---------------------------------------------------------------------
10  *
11  * Copyright (C) 2003 Dr. Heinz M. Kabutz [h.kabutz@computer.org]
12  *
13  * This library is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU Lesser General Public
15  * License as published by the Free Software Foundation; either
16  * version 2.1 of the License, or (at your option) any later version.
17  *
18  * This library is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21  * Lesser General Public License for more details.
22  *
23  * You should have received a copy of the GNU Lesser General Public
24  * License along with this library; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26  *
27  * $Id: SoftHashMap.java,v 1.4 2004/02/01 05:16:28 christianc Exp $
28  */

29 package org.enhydra.barracuda.plankton.data;
30
31 //: SoftHashMap.java
32
import java.util.*;
33 import java.lang.ref.*;
34
35 public class SoftHashMap extends AbstractMap {
36
37     /** The internal HashMap that will hold the SoftReference. */
38     private final Map hash = new HashMap();
39     /** The number of "hard" references to hold internally. */
40     private final int HARD_SIZE;
41     /** The FIFO list of hard references, order of last access. */
42     private final LinkedList hardCache = new LinkedList();
43     /** Reference queue for cleared SoftReference objects. */
44     private final ReferenceQueue queue = new ReferenceQueue();
45
46     public SoftHashMap() { this(100); }
47     public SoftHashMap(int hardSize) { HARD_SIZE = hardSize; }
48
49     public Object JavaDoc get(Object JavaDoc key) {
50         Object JavaDoc result = null;
51         // We get the SoftReference represented by that key
52
SoftReference soft_ref = (SoftReference)hash.get(key);
53         if (soft_ref != null) {
54             // From the SoftReference we get the value, which can be
55
// null if it was not in the map, or it was removed in
56
// the processQueue() method defined below
57
result = soft_ref.get();
58             if (result == null) {
59                 // If the value has been garbage collected, remove the
60
// entry from the HashMap.
61
hash.remove(key);
62             } else {
63                 // We now add this object to the beginning of the hard
64
// reference queue. One reference can occur more than
65
// once, because lookups of the FIFO queue are slow, so
66
// we don't want to search through it each time to remove
67
// duplicates.
68
hardCache.addFirst(result);
69                 if (hardCache.size() > HARD_SIZE) {
70                     // Remove the last entry if list longer than HARD_SIZE
71
hardCache.removeLast();
72                 }
73             }
74         }
75         return result;
76     }
77
78     /** We define our own subclass of SoftReference which contains
79      not only the value but also the key to make it easier to find
80      the entry in the HashMap after it's been garbage collected. */

81     private static class SoftValue extends SoftReference {
82         private final Object JavaDoc key; // always make data member final
83
/** Did you know that an outer class can access private data
84         members and methods of an inner class? I didn't know that!
85         I thought it was only the inner class who could access the
86         outer class's private information. An outer class can also
87         access private members of an inner class inside its inner
88         class. */

89         private SoftValue(Object JavaDoc k, Object JavaDoc key, ReferenceQueue q) {
90             super(k, q);
91             this.key = key;
92         }
93     }
94
95     /** Here we go through the ReferenceQueue and remove garbage
96      collected SoftValue objects from the HashMap by looking them
97      up using the SoftValue.key data member. */

98     private void processQueue() {
99         SoftValue sv;
100         while ((sv = (SoftValue)queue.poll()) != null) {
101             hash.remove(sv.key); // we can access private data!
102
}
103     }
104     /** Here we put the key, value pair into the HashMap using
105      a SoftValue object. */

106     public Object JavaDoc put(Object JavaDoc key, Object JavaDoc value) {
107         processQueue(); // throw out garbage collected values first
108
return hash.put(key, new SoftValue(value, key, queue));
109     }
110     public Object JavaDoc remove(Object JavaDoc key) {
111         processQueue(); // throw out garbage collected values first
112
return hash.remove(key);
113     }
114     public void clear() {
115         hardCache.clear();
116         processQueue(); // throw out garbage collected values
117
hash.clear();
118     }
119     public int size() {
120         processQueue(); // throw out garbage collected values first
121
return hash.size();
122     }
123     public Set entrySet() {
124         processQueue(); // throw out garbage collected values first
125
return hash.entrySet();
126     }
127 }
Popular Tags