KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > compiler > util > WeakHashSetOfCharArray


1 /*******************************************************************************
2  * Copyright (c) 2004 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.compiler.util;
12 import java.lang.ref.ReferenceQueue JavaDoc;
13 import java.lang.ref.WeakReference JavaDoc;
14
15 import org.eclipse.jdt.core.compiler.CharOperation;
16
17 /**
18  * A hashset of char[] whose values can be garbage collected.
19  */

20 public class WeakHashSetOfCharArray {
21     
22     public class HashableWeakReference extends WeakReference JavaDoc {
23         public int hashCode;
24         public HashableWeakReference(char[] referent, ReferenceQueue JavaDoc queue) {
25             super(referent, queue);
26             this.hashCode = CharOperation.hashCode(referent);
27         }
28         public boolean equals(Object JavaDoc obj) {
29             if (!(obj instanceof HashableWeakReference)) return false;
30             char[] referent = (char[]) get();
31             char[] other = (char[]) ((HashableWeakReference) obj).get();
32             if (referent == null) return other == null;
33             return CharOperation.equals(referent, other);
34         }
35         public int hashCode() {
36             return this.hashCode;
37         }
38         public String JavaDoc toString() {
39             char[] referent = (char[]) get();
40             if (referent == null) return "[hashCode=" + this.hashCode + "] <referent was garbage collected>"; //$NON-NLS-1$ //$NON-NLS-2$
41
return "[hashCode=" + this.hashCode + "] \"" + new String JavaDoc(referent) + '\"'; //$NON-NLS-1$ //$NON-NLS-2$
42
}
43     }
44     
45     HashableWeakReference[] values;
46     public int elementSize; // number of elements in the table
47
int threshold;
48     ReferenceQueue JavaDoc referenceQueue = new ReferenceQueue JavaDoc();
49     
50     public WeakHashSetOfCharArray() {
51         this(5);
52     }
53     
54     public WeakHashSetOfCharArray(int size) {
55         this.elementSize = 0;
56         this.threshold = size; // size represents the expected number of elements
57
int extraRoom = (int) (size * 1.75f);
58         if (this.threshold == extraRoom)
59             extraRoom++;
60         this.values = new HashableWeakReference[extraRoom];
61     }
62     
63     /*
64      * Adds the given char array to this set.
65      * If a char array that is equals to the given char array already exists, do nothing.
66      * Returns the existing char array or the new char array if not found.
67      */

68     public char[] add(char[] array) {
69         cleanupGarbageCollectedValues();
70         int index = (CharOperation.hashCode(array) & 0x7FFFFFFF) % this.values.length;
71         HashableWeakReference currentValue;
72         while ((currentValue = this.values[index]) != null) {
73             char[] referent;
74             if (CharOperation.equals(array, referent = (char[]) currentValue.get())) {
75                 return referent;
76             }
77             index = (index + 1) % this.values.length;
78         }
79         this.values[index] = new HashableWeakReference(array, this.referenceQueue);
80
81         // assumes the threshold is never equal to the size of the table
82
if (++this.elementSize > this.threshold)
83             rehash();
84         
85         return array;
86     }
87         
88     private void addValue(HashableWeakReference value) {
89         char[] array = (char[]) value.get();
90         if (array == null) return;
91         int valuesLength = this.values.length;
92         int index = (value.hashCode & 0x7FFFFFFF) % valuesLength;
93         HashableWeakReference currentValue;
94         while ((currentValue = this.values[index]) != null) {
95             if (CharOperation.equals(array, (char[]) currentValue.get())) {
96                 return;
97             }
98             index = (index + 1) % valuesLength;
99         }
100         this.values[index] = value;
101
102         // assumes the threshold is never equal to the size of the table
103
if (++this.elementSize > this.threshold)
104             rehash();
105     }
106     
107     private void cleanupGarbageCollectedValues() {
108         HashableWeakReference toBeRemoved;
109         while ((toBeRemoved = (HashableWeakReference) this.referenceQueue.poll()) != null) {
110             int hashCode = toBeRemoved.hashCode;
111             int valuesLength = this.values.length;
112             int index = (hashCode & 0x7FFFFFFF) % valuesLength;
113             HashableWeakReference currentValue;
114             while ((currentValue = this.values[index]) != null) {
115                 if (currentValue == toBeRemoved) {
116                     // replace the value at index with the last value with the same hash
117
int sameHash = index;
118                     int current;
119                     while ((currentValue = this.values[current = (sameHash + 1) % valuesLength]) != null && currentValue.hashCode == hashCode)
120                         sameHash = current;
121                     this.values[index] = this.values[sameHash];
122                     this.values[sameHash] = null;
123                     this.elementSize--;
124                     break;
125                 }
126                 index = (index + 1) % valuesLength;
127             }
128         }
129     }
130     
131     public boolean contains(char[] array) {
132         return get(array) != null;
133     }
134     
135     /*
136      * Return the char array that is in this set and that is equals to the given char array.
137      * Return null if not found.
138      */

139     public char[] get(char[] array) {
140         cleanupGarbageCollectedValues();
141         int valuesLength = this.values.length;
142         int index = (CharOperation.hashCode(array) & 0x7FFFFFFF) % valuesLength;
143         HashableWeakReference currentValue;
144         while ((currentValue = this.values[index]) != null) {
145             char[] referent;
146             if (CharOperation.equals(array, referent = (char[]) currentValue.get())) {
147                 return referent;
148             }
149             index = (index + 1) % valuesLength;
150         }
151         return null;
152     }
153         
154     private void rehash() {
155         WeakHashSetOfCharArray newHashSet = new WeakHashSetOfCharArray(this.elementSize * 2); // double the number of expected elements
156
newHashSet.referenceQueue = this.referenceQueue;
157         HashableWeakReference currentValue;
158         for (int i = 0, length = this.values.length; i < length; i++)
159             if ((currentValue = this.values[i]) != null)
160                 newHashSet.addValue(currentValue);
161
162         this.values = newHashSet.values;
163         this.threshold = newHashSet.threshold;
164         this.elementSize = newHashSet.elementSize;
165     }
166
167     /*
168      * Removes the char array that is in this set and that is equals to the given char array.
169      * Return the char array that was in the set, or null if not found.
170      */

171     public char[] remove(char[] array) {
172         cleanupGarbageCollectedValues();
173         int valuesLength = this.values.length;
174         int index = (CharOperation.hashCode(array) & 0x7FFFFFFF) % valuesLength;
175         HashableWeakReference currentValue;
176         while ((currentValue = this.values[index]) != null) {
177             char[] referent;
178             if (CharOperation.equals(array, referent = (char[]) currentValue.get())) {
179                 this.elementSize--;
180                 this.values[index] = null;
181                 rehash();
182                 return referent;
183             }
184             index = (index + 1) % valuesLength;
185         }
186         return null;
187     }
188
189     public int size() {
190         return this.elementSize;
191     }
192
193     public String JavaDoc toString() {
194         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc("{"); //$NON-NLS-1$
195
for (int i = 0, length = this.values.length; i < length; i++) {
196             HashableWeakReference value = this.values[i];
197             if (value != null) {
198                 char[] ref = (char[]) value.get();
199                 if (ref != null) {
200                     buffer.append('\"');
201                     buffer.append(ref);
202                     buffer.append("\", "); //$NON-NLS-1$
203
}
204             }
205         }
206         buffer.append("}"); //$NON-NLS-1$
207
return buffer.toString();
208     }
209 }
210
Popular Tags