KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > go > trove > util > MultiKey


1 /* ====================================================================
2  * Trove - Copyright (c) 1997-2000 Walt Disney Internet Group
3  * ====================================================================
4  * The Tea Software License, Version 1.1
5  *
6  * Copyright (c) 2000 Walt Disney Internet Group. All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Walt Disney Internet Group (http://opensource.go.com/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Tea", "TeaServlet", "Kettle", "Trove" and "BeanDoc" must
28  * not be used to endorse or promote products derived from this
29  * software without prior written permission. For written
30  * permission, please contact opensource@dig.com.
31  *
32  * 5. Products derived from this software may not be called "Tea",
33  * "TeaServlet", "Kettle" or "Trove", nor may "Tea", "TeaServlet",
34  * "Kettle", "Trove" or "BeanDoc" appear in their name, without prior
35  * written permission of the Walt Disney Internet Group.
36  *
37  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40  * DISCLAIMED. IN NO EVENT SHALL THE WALT DISNEY INTERNET GROUP OR ITS
41  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
42  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
43  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
44  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
45  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
46  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
47  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
48  * ====================================================================
49  *
50  * For more information about Tea, please see http://opensource.go.com/.
51  */

52
53 package com.go.trove.util;
54
55 import java.util.Arrays JavaDoc;
56
57 /******************************************************************************
58  * MultiKey allows arrays and arrays of arrays to be used as hashtable keys.
59  * Hashcode computation and equality tests will fully recurse into the array
60  * elements. MultiKey can be used in conjunction with {@link Depot} for
61  * caching against complex keys.
62  *
63  * @author Brian S O'Neill
64  * @version
65  * <!--$$Revision:--> 4 <!-- $-->, <!--$$JustDate:--> 01/07/09 <!-- $-->
66  * @see Pair
67  */

68 public class MultiKey implements java.io.Serializable JavaDoc {
69     /**
70      * Computes an object hashcode for any kind of object including null,
71      * arrays, and arrays of arrays.
72      */

73     static int hashCode(Object JavaDoc obj) {
74         if (obj == null) {
75             return 0;
76         }
77
78         Class JavaDoc clazz = obj.getClass();
79
80         if (!clazz.isArray()) {
81             return obj.hashCode();
82         }
83         
84         // Compute hashcode of array.
85

86         int hash = clazz.hashCode();
87         
88         if (obj instanceof Object JavaDoc[]) {
89             Object JavaDoc[] array = (Object JavaDoc[])obj;
90             for (int i = array.length; --i >= 0; ) {
91                 hash = hash * 31 + hashCode(array[i]);
92             }
93         }
94         else if (obj instanceof int[]) {
95             int[] array = (int[])obj;
96             for (int i = array.length; --i >= 0; ) {
97                 hash = hash * 31 + array[i];
98             }
99         }
100         else if (obj instanceof float[]) {
101             float[] array = (float[])obj;
102             for (int i = array.length; --i >= 0; ) {
103                 hash = hash * 31 + Float.floatToIntBits(array[i]);
104             }
105         }
106         else if (obj instanceof long[]) {
107             long[] array = (long[])obj;
108             for (int i = array.length; --i >= 0; ) {
109                 long value = array[i];
110                 hash = hash * 31 + (int)(value ^ value >>> 32);
111             }
112         }
113         else if (obj instanceof double[]) {
114             double[] array = (double[])obj;
115             for (int i = array.length; --i >= 0; ) {
116                 long value = Double.doubleToLongBits(array[i]);
117                 hash = hash * 31 + (int)(value ^ value >>> 32);
118             }
119         }
120         else if (obj instanceof byte[]) {
121             byte[] array = (byte[])obj;
122             for (int i = array.length; --i >= 0; ) {
123                 hash = hash * 31 + array[i];
124             }
125         }
126         else if (obj instanceof char[]) {
127             char[] array = (char[])obj;
128             for (int i = array.length; --i >= 0; ) {
129                 hash = hash * 31 + array[i];
130             }
131         }
132         else if (obj instanceof boolean[]) {
133             boolean[] array = (boolean[])obj;
134             for (int i = array.length; --i >= 0; ) {
135                 hash = hash * 31 + (array[i] ? 1 : 0);
136             }
137         }
138         else if (obj instanceof short[]) {
139             short[] array = (short[])obj;
140             for (int i = array.length; --i >= 0; ) {
141                 hash = hash * 31 + array[i];
142             }
143         }
144         
145         return hash;
146     }
147     
148     /**
149      * Performans an object equality for any kind of objects including null,
150      * arrays, and arrays of arrays.
151      */

152     static boolean equals(Object JavaDoc obj1, Object JavaDoc obj2) {
153         if (obj1 == obj2) {
154             return true;
155         }
156         else if (obj1 == null || obj2 == null) {
157             return false;
158         }
159
160         Class JavaDoc clazz1 = obj1.getClass();
161
162         if (!(clazz1.isArray())) {
163             return obj1.equals(obj2);
164         }
165         
166         if (clazz1 != obj2.getClass()) {
167             return false;
168         }
169         
170         // Perform array equality test.
171
if (obj1 instanceof Object JavaDoc[]) {
172             // Don't use Arrays.equals for objects since it doesn't
173
// recurse into arrays of arrays.
174
Object JavaDoc[] array1 = (Object JavaDoc[])obj1;
175             Object JavaDoc[] array2 = (Object JavaDoc[])obj2;
176             
177             int i;
178             if ((i = array1.length) != array2.length) {
179                 return false;
180             }
181             
182             while (--i >= 0) {
183                 if (!equals(array1[i], array2[i])) {
184                     return false;
185                 }
186             }
187             
188             return true;
189         }
190         else if (obj1 instanceof int[]) {
191             return Arrays.equals((int[])obj1, (int[])obj2);
192         }
193         else if (obj1 instanceof float[]) {
194             return Arrays.equals((float[])obj1, (float[])obj2);
195         }
196         else if (obj1 instanceof long[]) {
197             return Arrays.equals((long[])obj1, (long[])obj2);
198         }
199         else if (obj1 instanceof double[]) {
200             return Arrays.equals((double[])obj1, (double[])obj2);
201         }
202         else if (obj1 instanceof byte[]) {
203             return Arrays.equals((byte[])obj1, (byte[])obj2);
204         }
205         else if (obj1 instanceof char[]) {
206             return Arrays.equals((char[])obj1, (char[])obj2);
207         }
208         else if (obj1 instanceof boolean[]) {
209             return Arrays.equals((boolean[])obj1, (boolean[])obj2);
210         }
211         else if (obj1 instanceof short[]) {
212             return Arrays.equals((short[])obj1, (short[])obj2);
213         }
214         else {
215             return obj1.equals(obj2);
216         }
217     }
218
219     private final Object JavaDoc mComponent;
220     private final int mHash;
221
222     /**
223      * Contruct a new MultiKey against a component which may be any kind of
224      * object including an array, or an array of arrays, or null.
225      */

226     public MultiKey(Object JavaDoc component) {
227         mComponent = component;
228         mHash = MultiKey.hashCode(component);
229     }
230
231     /**
232      * Returns the original component used to construct this MultiKey.
233      */

234     public Object JavaDoc getComponent() {
235         return mComponent;
236     }
237
238     public int hashCode() {
239         return mHash;
240     }
241
242     public boolean equals(Object JavaDoc other) {
243         if (this == other) {
244             return true;
245         }
246         else if (other instanceof MultiKey) {
247             MultiKey key = (MultiKey)other;
248             return MultiKey.equals(mComponent, key.mComponent);
249         }
250         else {
251             return false;
252         }
253     }
254
255     public String JavaDoc toString() {
256         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
257         append(buf, mComponent);
258         return buf.toString();
259     }
260
261     private void append(StringBuffer JavaDoc buf, Object JavaDoc obj) {
262         if (obj == null) {
263             buf.append("null");
264             return;
265         }
266
267         if (!obj.getClass().isArray()) {
268             buf.append(obj);
269             return;
270         }
271
272         buf.append('[');
273
274         if (obj instanceof Object JavaDoc[]) {
275             Object JavaDoc[] array = (Object JavaDoc[])obj;
276             for (int i=0; i<array.length; i++) {
277                 if (i > 0) {
278                     buf.append(',');
279                 }
280                 append(buf, array[i]);
281             }
282         }
283         else if (obj instanceof int[]) {
284             int[] array = (int[])obj;
285             for (int i=0; i<array.length; i++) {
286                 if (i > 0) {
287                     buf.append(',');
288                 }
289                 buf.append(array[i]);
290             }
291         }
292         else if (obj instanceof float[]) {
293             float[] array = (float[])obj;
294             for (int i=0; i<array.length; i++) {
295                 if (i > 0) {
296                     buf.append(',');
297                 }
298                 buf.append(array[i]);
299             }
300         }
301         else if (obj instanceof long[]) {
302             long[] array = (long[])obj;
303             for (int i=0; i<array.length; i++) {
304                 if (i > 0) {
305                     buf.append(',');
306                 }
307                 buf.append(array[i]);
308             }
309         }
310         else if (obj instanceof double[]) {
311             double[] array = (double[])obj;
312             for (int i=0; i<array.length; i++) {
313                 if (i > 0) {
314                     buf.append(',');
315                 }
316                 buf.append(array[i]);
317             }
318         }
319         else if (obj instanceof byte[]) {
320             byte[] array = (byte[])obj;
321             for (int i=0; i<array.length; i++) {
322                 if (i > 0) {
323                     buf.append(',');
324                 }
325                 buf.append(array[i]);
326             }
327         }
328         else if (obj instanceof char[]) {
329             char[] array = (char[])obj;
330             for (int i=0; i<array.length; i++) {
331                 if (i > 0) {
332                     buf.append(',');
333                 }
334                 buf.append(array[i]);
335             }
336         }
337         else if (obj instanceof boolean[]) {
338             boolean[] array = (boolean[])obj;
339             for (int i=0; i<array.length; i++) {
340                 if (i > 0) {
341                     buf.append(',');
342                 }
343                 buf.append(array[i]);
344             }
345         }
346         else if (obj instanceof short[]) {
347             short[] array = (short[])obj;
348             for (int i=0; i<array.length; i++) {
349                 if (i > 0) {
350                     buf.append(',');
351                 }
352                 buf.append(array[i]);
353             }
354         }
355         else {
356             buf.append(obj);
357         }
358
359         buf.append(']');
360     }
361 }
362
Popular Tags