1 12 13 package org.eclipse.jdt.internal.ui.packageview; 14 15 import java.util.Enumeration ; 16 import java.util.NoSuchElementException ; 17 18 import org.eclipse.jface.viewers.IElementComparer; 19 20 30 final class CustomHashtable { 31 32 35 private static class HashMapEntry { 36 Object key, value; 37 38 HashMapEntry next; 39 40 HashMapEntry(Object theKey, Object theValue) { 41 key = theKey; 42 value = theValue; 43 } 44 } 45 46 private static final class EmptyEnumerator implements Enumeration { 47 public boolean hasMoreElements() { 48 return false; 49 } 50 51 public Object nextElement() { 52 throw new NoSuchElementException (); 53 } 54 } 55 56 private class HashEnumerator implements Enumeration { 57 boolean key; 58 59 int start; 60 61 HashMapEntry entry; 62 63 HashEnumerator(boolean isKey) { 64 key = isKey; 65 start = firstSlot; 66 } 67 68 public boolean hasMoreElements() { 69 if (entry != null) 70 return true; 71 while (start <= lastSlot) 72 if (elementData[start++] != null) { 73 entry = elementData[start - 1]; 74 return true; 75 } 76 return false; 77 } 78 79 public Object nextElement() { 80 if (hasMoreElements()) { 81 Object result = key ? entry.key : entry.value; 82 entry = entry.next; 83 return result; 84 } else 85 throw new NoSuchElementException (); 86 } 87 } 88 89 transient int elementCount; 90 91 transient HashMapEntry[] elementData; 92 93 private float loadFactor; 94 95 private int threshold; 96 97 transient int firstSlot = 0; 98 99 transient int lastSlot = -1; 100 101 transient private IElementComparer comparer; 102 103 private static final EmptyEnumerator emptyEnumerator = new EmptyEnumerator(); 104 105 108 public static final int DEFAULT_CAPACITY = 13; 109 110 114 public CustomHashtable() { 115 this(13); 116 } 117 118 124 public CustomHashtable(int capacity) { 125 this(capacity, null); 126 } 127 128 136 public CustomHashtable(IElementComparer comparer) { 137 this(DEFAULT_CAPACITY, comparer); 138 } 139 140 150 public CustomHashtable(int capacity, IElementComparer comparer) { 151 if (capacity >= 0) { 152 elementCount = 0; 153 elementData = new HashMapEntry[capacity == 0 ? 1 : capacity]; 154 firstSlot = elementData.length; 155 loadFactor = 0.75f; 156 computeMaxSize(); 157 } else 158 throw new IllegalArgumentException (); 159 this.comparer = comparer; 160 } 161 162 172 public CustomHashtable(CustomHashtable table, IElementComparer comparer) { 173 this(table.size() * 2, comparer); 174 for (int i = table.elementData.length; --i >= 0;) { 175 HashMapEntry entry = table.elementData[i]; 176 while (entry != null) { 177 put(entry.key, entry.value); 178 entry = entry.next; 179 } 180 } 181 } 182 183 private void computeMaxSize() { 184 threshold = (int) (elementData.length * loadFactor); 185 } 186 187 194 public boolean containsKey(Object key) { 195 return getEntry(key) != null; 196 } 197 198 205 public Enumeration elements() { 206 if (elementCount == 0) 207 return emptyEnumerator; 208 return new HashEnumerator(false); 209 } 210 211 219 public Object get(Object key) { 220 int index = (hashCode(key) & 0x7FFFFFFF) % elementData.length; 221 HashMapEntry entry = elementData[index]; 222 while (entry != null) { 223 if (keyEquals(key, entry.key)) 224 return entry.value; 225 entry = entry.next; 226 } 227 return null; 228 } 229 230 private HashMapEntry getEntry(Object key) { 231 int index = (hashCode(key) & 0x7FFFFFFF) % elementData.length; 232 HashMapEntry entry = elementData[index]; 233 while (entry != null) { 234 if (keyEquals(key, entry.key)) 235 return entry; 236 entry = entry.next; 237 } 238 return null; 239 } 240 241 244 private int hashCode(Object key) { 245 if (comparer == null) 246 return key.hashCode(); 247 else 248 return comparer.hashCode(key); 249 } 250 251 254 private boolean keyEquals(Object a, Object b) { 255 if (comparer == null) 256 return a.equals(b); 257 else 258 return comparer.equals(a, b); 259 } 260 261 268 public Enumeration keys() { 269 if (elementCount == 0) 270 return emptyEnumerator; 271 return new HashEnumerator(true); 272 } 273 274 284 public Object put(Object key, Object value) { 285 if (key != null && value != null) { 286 int index = (hashCode(key) & 0x7FFFFFFF) % elementData.length; 287 HashMapEntry entry = elementData[index]; 288 while (entry != null && !keyEquals(key, entry.key)) 289 entry = entry.next; 290 if (entry == null) { 291 if (++elementCount > threshold) { 292 rehash(); 293 index = (hashCode(key) & 0x7FFFFFFF) % elementData.length; 294 } 295 if (index < firstSlot) 296 firstSlot = index; 297 if (index > lastSlot) 298 lastSlot = index; 299 entry = new HashMapEntry(key, value); 300 entry.next = elementData[index]; 301 elementData[index] = entry; 302 return null; 303 } 304 Object result = entry.value; 305 entry.key = key; entry.value = value; 307 return result; 308 } else 309 throw new NullPointerException (); 310 } 311 312 316 private void rehash() { 317 int length = elementData.length << 1; 318 if (length == 0) 319 length = 1; 320 firstSlot = length; 321 lastSlot = -1; 322 HashMapEntry[] newData = new HashMapEntry[length]; 323 for (int i = elementData.length; --i >= 0;) { 324 HashMapEntry entry = elementData[i]; 325 while (entry != null) { 326 int index = (hashCode(entry.key) & 0x7FFFFFFF) % length; 327 if (index < firstSlot) 328 firstSlot = index; 329 if (index > lastSlot) 330 lastSlot = index; 331 HashMapEntry next = entry.next; 332 entry.next = newData[index]; 333 newData[index] = entry; 334 entry = next; 335 } 336 } 337 elementData = newData; 338 computeMaxSize(); 339 } 340 341 348 public Object remove(Object key) { 349 HashMapEntry last = null; 350 int index = (hashCode(key) & 0x7FFFFFFF) % elementData.length; 351 HashMapEntry entry = elementData[index]; 352 while (entry != null && !keyEquals(key, entry.key)) { 353 last = entry; 354 entry = entry.next; 355 } 356 if (entry != null) { 357 if (last == null) 358 elementData[index] = entry.next; 359 else 360 last.next = entry.next; 361 elementCount--; 362 return entry.value; 363 } 364 return null; 365 } 366 367 372 public int size() { 373 return elementCount; 374 } 375 376 381 public String toString() { 382 if (size() == 0) 383 return "{}"; 385 StringBuffer buffer = new StringBuffer (); 386 buffer.append('{'); 387 for (int i = elementData.length; --i >= 0;) { 388 HashMapEntry entry = elementData[i]; 389 while (entry != null) { 390 buffer.append(entry.key); 391 buffer.append('='); 392 buffer.append(entry.value); 393 buffer.append(", "); entry = entry.next; 395 } 396 } 397 if (elementCount > 0) 399 buffer.setLength(buffer.length() - 2); 400 buffer.append('}'); 401 return buffer.toString(); 402 } 403 } 404 | Popular Tags |