KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > cojen > util > KeyFactory


1 /*
2  * Copyright 2004 Brian S O'Neill
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.cojen.util;
18
19 import java.util.Arrays JavaDoc;
20
21 /**
22  * KeyFactory generates keys which can be hashed or compared for any kind of
23  * object including arrays, arrays of arrays, and null. All hashcode
24  * computations, equality tests, and ordering comparsisons fully recurse into
25  * arrays.
26  *
27  * @author Brian S O'Neill
28  */

29 public class KeyFactory {
30     static final Object JavaDoc NULL = new Comparable JavaDoc() {
31         public int compareTo(Object JavaDoc obj) {
32             return obj == this || obj == null ? 0 : 1;
33         }
34     };
35
36     public static Object JavaDoc createKey(boolean[] obj) {
37         return obj == null ? NULL : new BooleanArrayKey(obj);
38     }
39
40     public static Object JavaDoc createKey(byte[] obj) {
41         return obj == null ? NULL : new ByteArrayKey(obj);
42     }
43
44     public static Object JavaDoc createKey(char[] obj) {
45         return obj == null ? NULL : new CharArrayKey(obj);
46     }
47
48     public static Object JavaDoc createKey(double[] obj) {
49         return obj == null ? NULL : new DoubleArrayKey(obj);
50     }
51
52     public static Object JavaDoc createKey(float[] obj) {
53         return obj == null ? NULL : new FloatArrayKey(obj);
54     }
55
56     public static Object JavaDoc createKey(int[] obj) {
57         return obj == null ? NULL : new IntArrayKey(obj);
58     }
59
60     public static Object JavaDoc createKey(long[] obj) {
61         return obj == null ? NULL : new LongArrayKey(obj);
62     }
63
64     public static Object JavaDoc createKey(short[] obj) {
65         return obj == null ? NULL : new ShortArrayKey(obj);
66     }
67
68     public static Object JavaDoc createKey(Object JavaDoc[] obj) {
69         return obj == null ? NULL : new ObjectArrayKey(obj);
70     }
71
72     public static Object JavaDoc createKey(Object JavaDoc obj) {
73         if (obj == null) {
74             return NULL;
75         }
76         if (!obj.getClass().isArray()) {
77             return obj;
78         }
79         if (obj instanceof Object JavaDoc[]) {
80             return createKey((Object JavaDoc[])obj);
81         } else if (obj instanceof int[]) {
82             return createKey((int[])obj);
83         } else if (obj instanceof float[]) {
84             return createKey((float[])obj);
85         } else if (obj instanceof long[]) {
86             return createKey((long[])obj);
87         } else if (obj instanceof double[]) {
88             return createKey((double[])obj);
89         } else if (obj instanceof byte[]) {
90             return createKey((byte[])obj);
91         } else if (obj instanceof char[]) {
92             return createKey((char[])obj);
93         } else if (obj instanceof boolean[]) {
94             return createKey((boolean[])obj);
95         } else if (obj instanceof short[]) {
96             return createKey((short[])obj);
97         } else {
98             return obj;
99         }
100     }
101
102     static int hashCode(boolean[] a) {
103         int hash = 0;
104         for (int i = a.length; --i >= 0; ) {
105             hash = (hash << 1) + (a[i] ? 0 : 1);
106         }
107         return hash == 0 ? -1 : hash;
108     }
109
110     static int hashCode(byte[] a) {
111         int hash = 0;
112         for (int i = a.length; --i >= 0; ) {
113             hash = (hash << 1) + a[i];
114         }
115         return hash == 0 ? -1 : hash;
116     }
117
118     static int hashCode(char[] a) {
119         int hash = 0;
120         for (int i = a.length; --i >= 0; ) {
121             hash = (hash << 1) + a[i];
122         }
123         return hash == 0 ? -1 : hash;
124     }
125
126     static int hashCode(double[] a) {
127         int hash = 0;
128         for (int i = a.length; --i >= 0; ) {
129             long v = Double.doubleToLongBits(a[i]);
130             hash = hash * 31 + (int)(v ^ v >>> 32);
131         }
132         return hash == 0 ? -1 : hash;
133     }
134
135     static int hashCode(float[] a) {
136         int hash = 0;
137         for (int i = a.length; --i >= 0; ) {
138             hash = hash * 31 + Float.floatToIntBits(a[i]);
139         }
140         return hash == 0 ? -1 : hash;
141     }
142
143     static int hashCode(int[] a) {
144         int hash = 0;
145         for (int i = a.length; --i >= 0; ) {
146             hash = (hash << 1) + a[i];
147         }
148         return hash == 0 ? -1 : hash;
149     }
150
151     static int hashCode(long[] a) {
152         int hash = 0;
153         for (int i = a.length; --i >= 0; ) {
154             long v = a[i];
155             hash = hash * 31 + (int)(v ^ v >>> 32);
156         }
157         return hash == 0 ? -1 : hash;
158     }
159
160     static int hashCode(short[] a) {
161         int hash = 0;
162         for (int i = a.length; --i >= 0; ) {
163             hash = (hash << 1) + a[i];
164         }
165         return hash == 0 ? -1 : hash;
166     }
167
168     static int hashCode(Object JavaDoc[] a) {
169         int hash = 0;
170         for (int i = a.length; --i >= 0; ) {
171             hash = hash * 31 + hashCode(a[i]);
172         }
173         return hash == 0 ? -1 : hash;
174     }
175
176     // Compute object or array hashcode and recurses into arrays within.
177
static int hashCode(Object JavaDoc a) {
178         if (a == null) {
179             return -1;
180         }
181         if (!a.getClass().isArray()) {
182             return a.hashCode();
183         }
184         if (a instanceof Object JavaDoc[]) {
185             return hashCode((Object JavaDoc[])a);
186         } else if (a instanceof int[]) {
187             return hashCode((int[])a);
188         } else if (a instanceof float[]) {
189             return hashCode((float[])a);
190         } else if (a instanceof long[]) {
191             return hashCode((long[])a);
192         } else if (a instanceof double[]) {
193             return hashCode((double[])a);
194         } else if (a instanceof byte[]) {
195             return hashCode((byte[])a);
196         } else if (a instanceof char[]) {
197             return hashCode((char[])a);
198         } else if (a instanceof boolean[]) {
199             return hashCode((boolean[])a);
200         } else if (a instanceof short[]) {
201             return hashCode((short[])a);
202         } else {
203             int hash = a.getClass().hashCode();
204             return hash == 0 ? -1 : hash;
205         }
206     }
207
208     // Compares object arrays and recurses into arrays within.
209
static boolean equals(Object JavaDoc[] a, Object JavaDoc[] b) {
210         if (a == b) {
211             return true;
212         }
213         if (a == null || b == null) {
214             return false;
215         }
216         int i;
217         if ((i = a.length) != b.length) {
218             return false;
219         }
220         while (--i >= 0) {
221             if (!equals(a[i], b[i])) {
222                 return false;
223             }
224         }
225         return true;
226     }
227
228     // Compares objects or arrays and recurses into arrays within.
229
static boolean equals(Object JavaDoc a, Object JavaDoc b) {
230         if (a == b) {
231             return true;
232         }
233         if (a == null || b == null) {
234             return false;
235         }
236         Class JavaDoc ac = a.getClass();
237         if (!(ac.isArray())) {
238             return a.equals(b);
239         }
240         if (ac != b.getClass()) {
241             return false;
242         }
243         if (a instanceof Object JavaDoc[]) {
244             return equals((Object JavaDoc[])a, (Object JavaDoc[])b);
245         } else if (a instanceof int[]) {
246             return Arrays.equals((int[])a, (int[])b);
247         } else if (a instanceof float[]) {
248             return Arrays.equals((float[])a, (float[])b);
249         } else if (a instanceof long[]) {
250             return Arrays.equals((long[])a, (long[])b);
251         } else if (a instanceof double[]) {
252             return Arrays.equals((double[])a, (double[])b);
253         } else if (a instanceof byte[]) {
254             return Arrays.equals((byte[])a, (byte[])b);
255         } else if (a instanceof char[]) {
256             return Arrays.equals((char[])a, (char[])b);
257         } else if (a instanceof boolean[]) {
258             return Arrays.equals((boolean[])a, (boolean[])b);
259         } else if (a instanceof short[]) {
260             return Arrays.equals((short[])a, (short[])b);
261         } else {
262             return a.equals(b);
263         }
264     }
265
266     static int compare(boolean[] a, boolean[] b) {
267         if (a == b) {
268             return 0;
269         }
270         if (a == null) {
271             return 1;
272         }
273         if (b == null) {
274             return -1;
275         }
276         int length = Math.min(a.length, b.length);
277         for (int i=0; i<length; i++) {
278             int av = a[i] ? 0 : 1;
279             int bv = b[i] ? 0 : 1;
280             return av < bv ? -1 : (av > bv ? 1 : 0);
281         }
282         return a.length < b.length ? -1 : (a.length > b.length ? 1 : 0);
283     }
284
285     static int compare(byte[] a, byte[] b) {
286         if (a == b) {
287             return 0;
288         }
289         if (a == null) {
290             return 1;
291         }
292         if (b == null) {
293             return -1;
294         }
295         int length = Math.min(a.length, b.length);
296         for (int i=0; i<length; i++) {
297             byte av = a[i];
298             byte bv = b[i];
299             return av < bv ? -1 : (av > bv ? 1 : 0);
300         }
301         return a.length < b.length ? -1 : (a.length > b.length ? 1 : 0);
302     }
303
304     static int compare(char[] a, char[] b) {
305         if (a == b) {
306             return 0;
307         }
308         if (a == null) {
309             return 1;
310         }
311         if (b == null) {
312             return -1;
313         }
314         int length = Math.min(a.length, b.length);
315         for (int i=0; i<length; i++) {
316             char av = a[i];
317             char bv = b[i];
318             return av < bv ? -1 : (av > bv ? 1 : 0);
319         }
320         return a.length < b.length ? -1 : (a.length > b.length ? 1 : 0);
321     }
322
323     static int compare(double[] a, double[] b) {
324         if (a == b) {
325             return 0;
326         }
327         if (a == null) {
328             return 1;
329         }
330         if (b == null) {
331             return -1;
332         }
333         int length = Math.min(a.length, b.length);
334         for (int i=0; i<length; i++) {
335             int v = Double.compare(a[i], b[i]);
336             if (v != 0) {
337                 return v;
338             }
339         }
340         return a.length < b.length ? -1 : (a.length > b.length ? 1 : 0);
341     }
342
343     static int compare(float[] a, float[] b) {
344         if (a == b) {
345             return 0;
346         }
347         if (a == null) {
348             return 1;
349         }
350         if (b == null) {
351             return -1;
352         }
353         int length = Math.min(a.length, b.length);
354         for (int i=0; i<length; i++) {
355             int v = Float.compare(a[i], b[i]);
356             if (v != 0) {
357                 return v;
358             }
359         }
360         return a.length < b.length ? -1 : (a.length > b.length ? 1 : 0);
361     }
362
363     static int compare(int[] a, int[] b) {
364         if (a == b) {
365             return 0;
366         }
367         if (a == null) {
368             return 1;
369         }
370         if (b == null) {
371             return -1;
372         }
373         int length = Math.min(a.length, b.length);
374         for (int i=0; i<length; i++) {
375             int av = a[i];
376             int bv = b[i];
377             return av < bv ? -1 : (av > bv ? 1 : 0);
378         }
379         return a.length < b.length ? -1 : (a.length > b.length ? 1 : 0);
380     }
381
382     static int compare(long[] a, long[] b) {
383         if (a == b) {
384             return 0;
385         }
386         if (a == null) {
387             return 1;
388         }
389         if (b == null) {
390             return -1;
391         }
392         int length = Math.min(a.length, b.length);
393         for (int i=0; i<length; i++) {
394             long av = a[i];
395             long bv = b[i];
396             return av < bv ? -1 : (av > bv ? 1 : 0);
397         }
398         return a.length < b.length ? -1 : (a.length > b.length ? 1 : 0);
399     }
400
401     static int compare(short[] a, short[] b) {
402         if (a == b) {
403             return 0;
404         }
405         if (a == null) {
406             return 1;
407         }
408         if (b == null) {
409             return -1;
410         }
411         int length = Math.min(a.length, b.length);
412         for (int i=0; i<length; i++) {
413             short av = a[i];
414             short bv = b[i];
415             return av < bv ? -1 : (av > bv ? 1 : 0);
416         }
417         return a.length < b.length ? -1 : (a.length > b.length ? 1 : 0);
418     }
419
420     // Compares object arrays and recurses into arrays within.
421
static int compare(Object JavaDoc[] a, Object JavaDoc[] b) {
422         if (a == b) {
423             return 0;
424         }
425         if (a == null) {
426             return 1;
427         }
428         if (b == null) {
429             return -1;
430         }
431         int length = Math.min(a.length, b.length);
432         for (int i=0; i<length; i++) {
433             int v = compare(a[i], b[i]);
434             if (v != 0) {
435                 return v;
436             }
437         }
438         return a.length < b.length ? -1 : (a.length > b.length ? 1 : 0);
439     }
440
441     // Compares objects or arrays and recurses into arrays within.
442
static int compare(Object JavaDoc a, Object JavaDoc b) {
443         if (a == b) {
444             return 0;
445         }
446         if (a == null) {
447             return 1;
448         }
449         if (b == null) {
450             return -1;
451         }
452         Class JavaDoc ac = a.getClass();
453         if (!(ac.isArray())) {
454             return ((Comparable JavaDoc)a).compareTo(b);
455         }
456         if (ac != b.getClass()) {
457             throw new ClassCastException JavaDoc();
458         }
459         if (a instanceof Object JavaDoc[]) {
460             return compare((Object JavaDoc[])a, (Object JavaDoc[])b);
461         } else if (a instanceof int[]) {
462             return compare((int[])a, (int[])b);
463         } else if (a instanceof float[]) {
464             return compare((float[])a, (float[])b);
465         } else if (a instanceof long[]) {
466             return compare((long[])a, (long[])b);
467         } else if (a instanceof double[]) {
468             return compare((double[])a, (double[])b);
469         } else if (a instanceof byte[]) {
470             return compare((byte[])a, (byte[])b);
471         } else if (a instanceof char[]) {
472             return compare((char[])a, (char[])b);
473         } else if (a instanceof boolean[]) {
474             return compare((boolean[])a, (boolean[])b);
475         } else if (a instanceof short[]) {
476             return compare((short[])a, (short[])b);
477         } else {
478             throw new ClassCastException JavaDoc();
479         }
480     }
481
482     protected KeyFactory() {
483     }
484
485     private static interface ArrayKey extends Comparable JavaDoc, java.io.Serializable JavaDoc {
486         int hashCode();
487
488         boolean equals(Object JavaDoc obj);
489
490         int compareTo(Object JavaDoc obj);
491     }
492
493     private static class BooleanArrayKey implements ArrayKey {
494         protected final boolean[] mArray;
495         private transient int mHash;
496
497         BooleanArrayKey(boolean[] array) {
498             mArray = array;
499         }
500
501         public int hashCode() {
502             int hash = mHash;
503             return hash == 0 ? mHash = KeyFactory.hashCode(mArray) : hash;
504         }
505
506         public boolean equals(Object JavaDoc obj) {
507             return this == obj ? true :
508                 (obj instanceof BooleanArrayKey ?
509                  Arrays.equals(mArray, ((BooleanArrayKey) obj).mArray) : false);
510         }
511
512         public int compareTo(Object JavaDoc obj) {
513             return compare(mArray, ((BooleanArrayKey) obj).mArray);
514         }
515     }
516
517     private static class ByteArrayKey implements ArrayKey {
518         protected final byte[] mArray;
519         private transient int mHash;
520
521         ByteArrayKey(byte[] array) {
522             mArray = array;
523         }
524
525         public int hashCode() {
526             int hash = mHash;
527             return hash == 0 ? mHash = KeyFactory.hashCode(mArray) : hash;
528         }
529
530         public boolean equals(Object JavaDoc obj) {
531             return this == obj ? true :
532                 (obj instanceof ByteArrayKey ?
533                  Arrays.equals(mArray, ((ByteArrayKey) obj).mArray) : false);
534         }
535
536         public int compareTo(Object JavaDoc obj) {
537             return compare(mArray, ((ByteArrayKey) obj).mArray);
538         }
539     }
540
541     private static class CharArrayKey implements ArrayKey {
542         protected final char[] mArray;
543         private transient int mHash;
544
545         CharArrayKey(char[] array) {
546             mArray = array;
547         }
548
549         public int hashCode() {
550             int hash = mHash;
551             return hash == 0 ? mHash = KeyFactory.hashCode(mArray) : hash;
552         }
553
554         public boolean equals(Object JavaDoc obj) {
555             return this == obj ? true :
556                 (obj instanceof CharArrayKey ?
557                  Arrays.equals(mArray, ((CharArrayKey) obj).mArray) : false);
558         }
559
560         public int compareTo(Object JavaDoc obj) {
561             return compare(mArray, ((CharArrayKey) obj).mArray);
562         }
563     }
564
565     private static class DoubleArrayKey implements ArrayKey {
566         protected final double[] mArray;
567         private transient int mHash;
568
569         DoubleArrayKey(double[] array) {
570             mArray = array;
571         }
572
573         public int hashCode() {
574             int hash = mHash;
575             return hash == 0 ? mHash = KeyFactory.hashCode(mArray) : hash;
576         }
577
578         public boolean equals(Object JavaDoc obj) {
579             return this == obj ? true :
580                 (obj instanceof DoubleArrayKey ?
581                  Arrays.equals(mArray, ((DoubleArrayKey) obj).mArray) : false);
582         }
583
584         public int compareTo(Object JavaDoc obj) {
585             return compare(mArray, ((DoubleArrayKey) obj).mArray);
586         }
587     }
588
589     private static class FloatArrayKey implements ArrayKey {
590         protected final float[] mArray;
591         private transient int mHash;
592
593         FloatArrayKey(float[] array) {
594             mArray = array;
595         }
596
597         public int hashCode() {
598             int hash = mHash;
599             return hash == 0 ? mHash = KeyFactory.hashCode(mArray) : hash;
600         }
601
602         public boolean equals(Object JavaDoc obj) {
603             return this == obj ? true :
604                 (obj instanceof FloatArrayKey ?
605                  Arrays.equals(mArray, ((FloatArrayKey) obj).mArray) : false);
606         }
607
608         public int compareTo(Object JavaDoc obj) {
609             return compare(mArray, ((FloatArrayKey) obj).mArray);
610         }
611     }
612
613     private static class IntArrayKey implements ArrayKey {
614         protected final int[] mArray;
615         private transient int mHash;
616
617         IntArrayKey(int[] array) {
618             mArray = array;
619         }
620
621         public int hashCode() {
622             int hash = mHash;
623             return hash == 0 ? mHash = KeyFactory.hashCode(mArray) : hash;
624         }
625
626         public boolean equals(Object JavaDoc obj) {
627             return this == obj ? true :
628                 (obj instanceof IntArrayKey ?
629                  Arrays.equals(mArray, ((IntArrayKey) obj).mArray) : false);
630         }
631
632         public int compareTo(Object JavaDoc obj) {
633             return compare(mArray, ((IntArrayKey) obj).mArray);
634         }
635     }
636
637     private static class LongArrayKey implements ArrayKey {
638         protected final long[] mArray;
639         private transient int mHash;
640
641         LongArrayKey(long[] array) {
642             mArray = array;
643         }
644
645         public int hashCode() {
646             int hash = mHash;
647             return hash == 0 ? mHash = KeyFactory.hashCode(mArray) : hash;
648         }
649
650         public boolean equals(Object JavaDoc obj) {
651             return this == obj ? true :
652                 (obj instanceof LongArrayKey ?
653                  Arrays.equals(mArray, ((LongArrayKey) obj).mArray) : false);
654         }
655
656         public int compareTo(Object JavaDoc obj) {
657             return compare(mArray, ((LongArrayKey) obj).mArray);
658         }
659     }
660
661     private static class ShortArrayKey implements ArrayKey {
662         protected final short[] mArray;
663         private transient int mHash;
664
665         ShortArrayKey(short[] array) {
666             mArray = array;
667         }
668
669         public int hashCode() {
670             int hash = mHash;
671             return hash == 0 ? mHash = KeyFactory.hashCode(mArray) : hash;
672         }
673
674         public boolean equals(Object JavaDoc obj) {
675             return this == obj ? true :
676                 (obj instanceof ShortArrayKey ?
677                  Arrays.equals(mArray, ((ShortArrayKey) obj).mArray) : false);
678         }
679
680         public int compareTo(Object JavaDoc obj) {
681             return compare(mArray, ((ShortArrayKey) obj).mArray);
682         }
683     }
684
685     private static class ObjectArrayKey implements ArrayKey {
686         protected final Object JavaDoc[] mArray;
687         private transient int mHash;
688
689         ObjectArrayKey(Object JavaDoc[] array) {
690             mArray = array;
691         }
692
693         public int hashCode() {
694             int hash = mHash;
695             return hash == 0 ? mHash = KeyFactory.hashCode(mArray) : hash;
696         }
697
698         public boolean equals(Object JavaDoc obj) {
699             return this == obj ? true :
700                 (obj instanceof ObjectArrayKey ?
701                  KeyFactory.equals(mArray, ((ObjectArrayKey) obj).mArray) : false);
702         }
703
704         public int compareTo(Object JavaDoc obj) {
705             return compare(mArray, ((ObjectArrayKey) obj).mArray);
706         }
707     }
708 }
709
Popular Tags