KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > hsqldb > store > ValuePoolHashMap


1 /* Copyright (c) 2001-2005, The HSQL Development Group
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * Redistributions of source code must retain the above copyright notice, this
8  * list of conditions and the following disclaimer.
9  *
10  * Redistributions in binary form must reproduce the above copyright notice,
11  * this list of conditions and the following disclaimer in the documentation
12  * and/or other materials provided with the distribution.
13  *
14  * Neither the name of the HSQL Development Group nor the names of its
15  * contributors may be used to endorse or promote products derived from this
16  * software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
22  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */

30
31
32 package org.hsqldb.store;
33
34 import java.sql.Date JavaDoc;
35
36 /*
37  * implementation notes:
38  *
39  * NB: As of this version this class cannot be used for mixed object types
40  * It is relativly easy to support this by adding an 'instanceof' test inside
41  * each getOrAddXxxx method before casting the Set values to the target type
42  * for comparison purposes.
43  *
44  * superclass is used as an Object Set
45  * getOrAddXxxx methods are implemented directly for speed
46  * the superclass infrastructure is otherwise used
47  */

48
49 /**
50  * Subclass of BaseHashMap for maintaining a pool of objects. Supports a
51  * range of java.lang.* objects.
52  *
53  * @author fredt@users
54  * @version 1.8.0
55  * @since 1.7.2
56  *
57  */

58 public class ValuePoolHashMap extends BaseHashMap {
59
60     public ValuePoolHashMap(int initialCapacity, int maxCapacity,
61                             int purgePolicy) throws IllegalArgumentException JavaDoc {
62
63         super(initialCapacity, 1, BaseHashMap.objectKeyOrValue,
64               BaseHashMap.noKeyOrValue, true);
65
66         this.maxCapacity = maxCapacity;
67         this.purgePolicy = purgePolicy;
68     }
69
70     /**
71      * In rare circumstances resetCapacity may not succeed, in which case
72      * capacity remains unchanged but purge policy is set to newPolicy
73      */

74     public void resetCapacity(int newCapacity,
75                               int newPolicy) throws IllegalArgumentException JavaDoc {
76
77         if (newCapacity != 0 && hashIndex.elementCount > newCapacity) {
78             int surplus = hashIndex.elementCount - newCapacity;
79
80             surplus += (surplus >> 5);
81
82             if (surplus > hashIndex.elementCount) {
83                 surplus = hashIndex.elementCount;
84             }
85
86             clear(surplus, (surplus >> 6));
87         }
88
89         if (newCapacity != 0 && newCapacity < threshold) {
90             rehash(newCapacity);
91
92             if (newCapacity < hashIndex.elementCount) {
93                 newCapacity = maxCapacity;
94             }
95         }
96
97         this.maxCapacity = newCapacity;
98         this.purgePolicy = newPolicy;
99     }
100
101     protected Integer JavaDoc getOrAddInteger(int intKey) {
102
103         Integer JavaDoc testValue;
104         int index = hashIndex.getHashIndex(intKey);
105         int lookup = hashIndex.hashTable[index];
106         int lastLookup = -1;
107
108         for (; lookup >= 0;
109                 lastLookup = lookup,
110                 lookup = hashIndex.getNextLookup(lookup)) {
111             testValue = (Integer JavaDoc) objectKeyTable[lookup];
112
113             if (testValue.intValue() == intKey) {
114                 if (accessCount == Integer.MAX_VALUE) {
115                     resetAccessCount();
116                 }
117
118                 accessTable[lookup] = accessCount++;
119
120                 return testValue;
121             }
122         }
123
124         if (hashIndex.elementCount >= threshold) {
125             reset();
126
127             return getOrAddInteger(intKey);
128         }
129
130         lookup = hashIndex.linkNode(index, lastLookup);
131         testValue = new Integer JavaDoc(intKey);
132         objectKeyTable[lookup] = testValue;
133
134         if (accessCount == Integer.MAX_VALUE) {
135             resetAccessCount();
136         }
137
138         accessTable[lookup] = accessCount++;
139
140         return testValue;
141     }
142
143     protected Long JavaDoc getOrAddLong(long longKey) {
144
145         Long JavaDoc testValue;
146         int index = hashIndex.getHashIndex((int) (longKey
147             ^ (longKey >>> 32)));
148         int lookup = hashIndex.hashTable[index];
149         int lastLookup = -1;
150
151         for (; lookup >= 0;
152                 lastLookup = lookup,
153                 lookup = hashIndex.getNextLookup(lookup)) {
154             testValue = (Long JavaDoc) objectKeyTable[lookup];
155
156             if (testValue.longValue() == longKey) {
157                 if (accessCount == Integer.MAX_VALUE) {
158                     resetAccessCount();
159                 }
160
161                 accessTable[lookup] = accessCount++;
162
163                 return testValue;
164             }
165         }
166
167         if (hashIndex.elementCount >= threshold) {
168             reset();
169
170             return getOrAddLong(longKey);
171         }
172
173         lookup = hashIndex.linkNode(index, lastLookup);
174         testValue = new Long JavaDoc(longKey);
175         objectKeyTable[lookup] = testValue;
176
177         if (accessCount == Integer.MAX_VALUE) {
178             resetAccessCount();
179         }
180
181         accessTable[lookup] = accessCount++;
182
183         return testValue;
184     }
185
186     /**
187      * This is dissimilar to normal hash map get() methods. The key Object
188      * should have an equals(String) method which should return true if the
189      * key.toString.equals(String) is true. Also the key.hashCode() method
190      * must return the same value as key.toString.hashCode().<p>
191      *
192      * The above is always true when the key is a String. But it means it is
193      * possible to submit special keys that fulfill the contract. For example
194      * a wrapper around a byte[] can be submitted as key to retrieve either
195      * a new String, which is the toString() method of the wrapper, or return
196      * an existing String which would be equal to the product of toString().
197      *
198      * @param key String or other Object with compatible equals(String)
199      * and hashCode().
200      * @return String from map or a new String
201      */

202     protected String JavaDoc getOrAddString(Object JavaDoc key) {
203
204         String JavaDoc testValue;
205         int index = hashIndex.getHashIndex(key.hashCode());
206         int lookup = hashIndex.hashTable[index];
207         int lastLookup = -1;
208
209         for (; lookup >= 0;
210                 lastLookup = lookup,
211                 lookup = hashIndex.getNextLookup(lookup)) {
212             testValue = (String JavaDoc) objectKeyTable[lookup];
213
214             if (key.equals(testValue)) {
215                 if (accessCount == Integer.MAX_VALUE) {
216                     resetAccessCount();
217                 }
218
219                 accessTable[lookup] = accessCount++;
220
221                 return testValue;
222             }
223         }
224
225         if (hashIndex.elementCount >= threshold) {
226             reset();
227
228             return getOrAddString(key);
229         }
230
231         testValue = key.toString();
232         lookup = hashIndex.linkNode(index, lastLookup);
233         objectKeyTable[lookup] = testValue;
234
235         if (accessCount == Integer.MAX_VALUE) {
236             resetAccessCount();
237         }
238
239         accessTable[lookup] = accessCount++;
240
241         return testValue;
242     }
243
244     protected Date JavaDoc getOrAddDate(long longKey) {
245
246         Date JavaDoc testValue;
247         int hash = (int) longKey ^ (int) (longKey >>> 32);
248         int index = hashIndex.getHashIndex(hash);
249         int lookup = hashIndex.hashTable[index];
250         int lastLookup = -1;
251
252         for (; lookup >= 0;
253                 lastLookup = lookup,
254                 lookup = hashIndex.getNextLookup(lookup)) {
255             testValue = (Date JavaDoc) objectKeyTable[lookup];
256
257             if (testValue.getTime() == longKey) {
258                 if (accessCount == Integer.MAX_VALUE) {
259                     resetAccessCount();
260                 }
261
262                 accessTable[lookup] = accessCount++;
263
264                 return testValue;
265             }
266         }
267
268         if (hashIndex.elementCount >= threshold) {
269             reset();
270
271             return getOrAddDate(longKey);
272         }
273
274         lookup = hashIndex.linkNode(index, lastLookup);
275         testValue = new Date JavaDoc(longKey);
276         objectKeyTable[lookup] = testValue;
277
278         if (accessCount == Integer.MAX_VALUE) {
279             resetAccessCount();
280         }
281
282         accessTable[lookup] = accessCount++;
283
284         return testValue;
285     }
286
287     protected Double JavaDoc getOrAddDouble(long longKey) {
288
289         Double JavaDoc testValue;
290         int index = hashIndex.getHashIndex((int) (longKey
291             ^ (longKey >>> 32)));
292         int lookup = hashIndex.hashTable[index];
293         int lastLookup = -1;
294
295         for (; lookup >= 0;
296                 lastLookup = lookup,
297                 lookup = hashIndex.getNextLookup(lookup)) {
298             testValue = (Double JavaDoc) objectKeyTable[lookup];
299
300             if (Double.doubleToLongBits(testValue.doubleValue()) == longKey) {
301                 if (accessCount == Integer.MAX_VALUE) {
302                     resetAccessCount();
303                 }
304
305                 accessTable[lookup] = accessCount++;
306
307                 return testValue;
308             }
309         }
310
311         if (hashIndex.elementCount >= threshold) {
312             reset();
313
314             return getOrAddDouble(longKey);
315         }
316
317         lookup = hashIndex.linkNode(index, lastLookup);
318         testValue = new Double JavaDoc(Double.longBitsToDouble(longKey));
319         objectKeyTable[lookup] = testValue;
320
321         if (accessCount == Integer.MAX_VALUE) {
322             resetAccessCount();
323         }
324
325         accessTable[lookup] = accessCount++;
326
327         return testValue;
328     }
329
330     protected Object JavaDoc getOrAddObject(Object JavaDoc key) {
331
332         Object JavaDoc testValue;
333         int index = hashIndex.getHashIndex(key.hashCode());
334         int lookup = hashIndex.hashTable[index];
335         int lastLookup = -1;
336
337         for (; lookup >= 0;
338                 lastLookup = lookup,
339                 lookup = hashIndex.getNextLookup(lookup)) {
340             testValue = objectKeyTable[lookup];
341
342             if (testValue.equals(key)) {
343                 if (accessCount == Integer.MAX_VALUE) {
344                     resetAccessCount();
345                 }
346
347                 accessTable[lookup] = accessCount++;
348
349                 return testValue;
350             }
351         }
352
353         if (hashIndex.elementCount >= threshold) {
354             reset();
355
356             return getOrAddObject(key);
357         }
358
359         lookup = hashIndex.linkNode(index, lastLookup);
360         objectKeyTable[lookup] = key;
361
362         if (accessCount == Integer.MAX_VALUE) {
363             resetAccessCount();
364         }
365
366         accessTable[lookup] = accessCount++;
367
368         return key;
369     }
370 /*
371     public static void main(String[] argv) {
372
373         int BIGRANGE = 100000;
374         int SMALLRANGE = 50000;
375         int POOLSIZE = 100000;
376         java.util.Random randomgen = new java.util.Random();
377         org.hsqldb.lib.StopWatch sw = new org.hsqldb.lib.StopWatch();
378         ValuePoolHashMap map = new ValuePoolHashMap(POOLSIZE, POOLSIZE,
379             BaseHashMap.PURGE_HALF);
380         int maxCount = 5000000;
381
382         try {
383             for (int rounds = 0; rounds < 3; rounds++) {
384                 sw.zero();
385
386                 // timing for ValuePool retreival
387                 for (int i = 0; i < maxCount; i++) {
388                     boolean bigrange = (i % 2) == 0;
389                     int intValue = randomgen.nextInt(bigrange ? BIGRANGE
390                                                                    : SMALLRANGE);
391                     Integer intObject = map.getOrAddInteger(intValue);
392
393                     if (intObject.intValue() != intValue) {
394                         throw new Exception("Value mismatch");
395                     }
396
397                     // System.out.print(intValue);
398                     // System.out.print(' ');
399                 }
400
401                 System.out.println("Count " + maxCount + " "
402                                    + sw.elapsedTime());
403                 sw.zero();
404
405                 // timing for Integer creation
406                 for (int i = 0; i < maxCount; i++) {
407                     boolean bigrange = (i % 2) == 0;
408                     int intValue = randomgen.nextInt(bigrange ? BIGRANGE
409                                                                    : SMALLRANGE);
410                     Integer intObject = new Integer(intValue);
411
412                     if (intObject.intValue() != intValue) {
413                         throw new Exception("Value mismatch");
414                     }
415                 }
416
417                 System.out.println("Count new Integer() " + maxCount + " "
418                                    + sw.elapsedTime());
419             }
420         } catch (Exception e) {
421             e.printStackTrace();
422         }
423     }
424 */

425 }
426
Popular Tags