1
2
3
4
5
6
7
8 package org.xwt.util;
9
10 import java.util.*;
11
12
19 public class Hash {
20
25 private static Object placeholder = new Object();
26
27
28 private int usedslots = 0;
29
30
31 protected int size = 0;
32
33
34 private final int loadFactor;
35
36
37 private Object[] keys1 = null;
38
39
40 private Object[] keys2 = null;
41
42
43 private Object[] vals = null;
44
45
46 public int size() { return size; }
47
48
49 public void clear() {
50 size = 0;
51 usedslots = 0;
52 for(int i=0; i<vals.length; i++) {
53 vals[i] = null;
54 keys1[i] = null;
55 if (keys2 != null) keys2[i] = null;
56 }
57 }
58
59
60 public Enumeration keys() { return new HashEnum(); }
61
62 public Hash() { this(25, 3); }
63 public Hash(int initialcapacity, int loadFactor) {
64
65 initialcapacity = initialcapacity / 4;
66 initialcapacity = 4 * initialcapacity + 3;
67 keys1 = new Object[initialcapacity];
68 vals = new Object[initialcapacity];
69 this.loadFactor = loadFactor;
70 }
71
72 public void remove(Object k1) { remove(k1, null); }
73 public void remove(Object k1, Object k2) { put_(k1, k2, null); }
74
75 private void rehash() {
76 Object[] oldkeys1 = keys1;
77 Object[] oldkeys2 = keys2;
78 Object[] oldvals = vals;
79 keys1 = new Object[oldvals.length * 2];
80 keys2 = oldkeys2 == null ? null : new Object[oldvals.length * 2];
81 vals = new Object[oldvals.length * 2];
82 size = 0;
83 usedslots = 0;
84 for(int i=0; i<oldvals.length; i++)
85 if (((oldkeys1[i] != null && oldkeys1[i] != placeholder) || (oldkeys2 != null && oldkeys2[i] != null)) && oldvals[i] != null)
86 put_(oldkeys1[i], oldkeys2 == null ? null : oldkeys2[i], oldvals[i]);
87 }
88
89 public Object get(Object k1) { return get(k1, null); }
90 public Object get(Object k1, Object k2) {
91 if (k2 != null && keys2 == null) return null;
92 int hash = (k1 == null ? 0 : k1.hashCode()) ^ (k2 == null ? 0 : k2.hashCode());
93 int dest = Math.abs(hash) % vals.length;
94 int odest = dest;
95 int tries = 1;
96 boolean plus = true;
97 while (keys1[dest] != null || (keys2 != null && keys2[dest] != null)) {
98 Object hk1 = keys1[dest];
99 Object hk2 = keys2 == null ? null : keys2[dest];
100 if ((k1 == hk1 || (k1 != null && hk1 != null && k1.equals(hk1))) &&
101 (k2 == hk2 || (k2 != null && hk2 != null && k2.equals(hk2)))) {
102 return vals[dest];
103 }
104 dest = Math.abs((odest + (plus ? 1 : -1 ) * tries * tries) % vals.length);
105 if (plus) tries++;
106 plus = !plus;
107 }
108 return null;
109 }
110
111 public void put(Object k1, Object v) { put(k1, null, v); }
112 public void put(Object k1, Object k2, Object v) { put_(k1, k2, v); }
113 private void put_(Object k1, Object k2, Object v) {
114 if (usedslots * loadFactor > vals.length) rehash();
115 int hash = (k1 == null ? 0 : k1.hashCode()) ^ (k2 == null ? 0 : k2.hashCode());
116 int dest = Math.abs(hash) % vals.length;
117 int odest = dest;
118 boolean plus = true;
119 int tries = 1;
120 while (true) {
121 Object hk1 = keys1[dest];
122 Object hk2 = keys2 == null ? null : keys2[dest];
123 if (hk1 == null && hk2 == null) {
124 if (v == null) return;
125 size++;
126 usedslots++;
127 break;
128 }
129
130 if ((k1 == hk1 || (k1 != null && hk1 != null && k1.equals(hk1))) &&
131 (k2 == hk2 || (k2 != null && hk2 != null && k2.equals(hk2)))) {
132
133
134 if (v == null) {
135 k1 = placeholder;
136 k2 = null;
137 size--;
138 }
139 break;
140 }
141
142 dest = Math.abs((odest + (plus ? 1 : -1 ) * tries * tries) % vals.length);
143 if (plus) tries++;
144 plus = !plus;
145 }
146
147 keys1[dest] = k1;
148 if (k2 != null && keys2 == null) keys2 = new Object[keys1.length];
149 if (keys2 != null) keys2[dest] = k2;
150 vals[dest] = v;
151 }
152
153 private class HashEnum implements java.util.Enumeration {
154 private int iterator = 0;
155 private int found = 0;
156
157 public HashEnum () { }
158
159 public boolean hasMoreElements() {
160 return found < usedslots;
161 }
162
163 public Object nextElement() {
164 if (!hasMoreElements()) throw new java.util.NoSuchElementException();
165
166 Object o = null;
167 while (o == null) o = keys1[iterator++];
168 if (o == null) throw new IllegalStateException("Didn't find an element, when I should have.");
169 found++;
170
171 return o;
172 }
173 }
174 }
175
176
177