1 13 14 package org.eclipse.jdt.internal.junit.runner; 15 16 import java.util.Enumeration ; 17 import java.util.NoSuchElementException ; 18 19 22 public final class CustomHashtable { 23 24 28 private static class HashMapEntry { 29 30 Object key, value; 31 32 HashMapEntry next; 33 34 HashMapEntry(Object theKey, Object theValue) { 35 key= theKey; 36 value= theValue; 37 } 38 39 public String toString() { 40 StringBuffer buffer= new StringBuffer (); 41 appendToStringWithCommaNL(buffer); 42 int length= buffer.length(); 43 if (length >= 2) 44 return buffer.substring(0, length - 2); 45 else 46 return buffer.toString(); 47 } 48 49 private void appendToStringWithCommaNL(StringBuffer buffer) { 50 CustomHashtable.HashMapEntry hashMapEntry= this; 51 do { 52 buffer.append(hashMapEntry.key); 53 buffer.append('='); 54 buffer.append(hashMapEntry.value); 55 buffer.append(",\n"); hashMapEntry= hashMapEntry.next; 57 } while (hashMapEntry != null); 58 } 59 } 60 61 private static final class EmptyEnumerator implements Enumeration { 62 63 public boolean hasMoreElements() { 64 return false; 65 } 66 67 public Object nextElement() { 68 throw new NoSuchElementException (); 69 } 70 } 71 72 private class HashEnumerator implements Enumeration { 73 74 boolean key; 75 76 int start; 77 78 HashMapEntry entry; 79 80 HashEnumerator(boolean isKey) { 81 key= isKey; 82 start= firstSlot; 83 } 84 85 public boolean hasMoreElements() { 86 if (entry != null) 87 return true; 88 while (start <= lastSlot) 89 if (elementData[start++] != null) { 90 entry= elementData[start - 1]; 91 return true; 92 } 93 return false; 94 } 95 96 public Object nextElement() { 97 if (hasMoreElements()) { 98 Object result= key ? entry.key : entry.value; 99 entry= entry.next; 100 return result; 101 } else 102 throw new NoSuchElementException (); 103 } 104 } 105 106 transient int elementCount; 107 108 transient HashMapEntry[] elementData; 109 110 private float loadFactor; 111 112 private int threshold; 113 114 transient int firstSlot= 0; 115 116 transient int lastSlot= - 1; 117 118 transient private IElementComparer comparer; 119 120 private static final EmptyEnumerator emptyEnumerator= new EmptyEnumerator(); 121 122 125 public static final int DEFAULT_CAPACITY= 13; 126 127 130 public CustomHashtable() { 131 this(13); 132 } 133 134 140 public CustomHashtable(int capacity) { 141 this(capacity, null); 142 } 143 144 152 public CustomHashtable(IElementComparer comparer) { 153 this(DEFAULT_CAPACITY, comparer); 154 } 155 156 166 public CustomHashtable(int capacity, IElementComparer comparer) { 167 if (capacity >= 0) { 168 elementCount= 0; 169 elementData= new HashMapEntry[capacity == 0 ? 1 : capacity]; 170 firstSlot= elementData.length; 171 loadFactor= 0.75f; 172 computeMaxSize(); 173 } else 174 throw new IllegalArgumentException (); 175 this.comparer= comparer; 176 } 177 178 188 public CustomHashtable(CustomHashtable table, IElementComparer comparer) { 189 this(table.size() * 2, comparer); 190 for (int i= table.elementData.length; --i >= 0;) { 191 HashMapEntry entry= table.elementData[i]; 192 while (entry != null) { 193 put(entry.key, entry.value); 194 entry= entry.next; 195 } 196 } 197 } 198 199 private void computeMaxSize() { 200 threshold= (int) (elementData.length * loadFactor); 201 } 202 203 210 public boolean containsKey(Object key) { 211 return getEntry(key) != null; 212 } 213 214 221 public Enumeration elements() { 222 if (elementCount == 0) 223 return emptyEnumerator; 224 return new HashEnumerator(false); 225 } 226 227 234 public Object get(Object key) { 235 int index= (hashCode(key) & 0x7FFFFFFF) % elementData.length; 236 HashMapEntry entry= elementData[index]; 237 while (entry != null) { 238 if (keyEquals(key, entry.key)) 239 return entry.value; 240 entry= entry.next; 241 } 242 return null; 243 } 244 245 251 public Object getKey(Object key) { 252 int index= (hashCode(key) & 0x7FFFFFFF) % elementData.length; 253 HashMapEntry entry= elementData[index]; 254 while (entry != null) { 255 if (keyEquals(key, entry.key)) 256 return entry.key; 257 entry= entry.next; 258 } 259 return null; 260 } 261 262 private HashMapEntry getEntry(Object key) { 263 int index= (hashCode(key) & 0x7FFFFFFF) % elementData.length; 264 HashMapEntry entry= elementData[index]; 265 while (entry != null) { 266 if (keyEquals(key, entry.key)) 267 return entry; 268 entry= entry.next; 269 } 270 return null; 271 } 272 273 276 private int hashCode(Object key) { 277 if (comparer == null) 278 return key.hashCode(); 279 else 280 return comparer.hashCode(key); 281 } 282 283 286 private boolean keyEquals(Object a, Object b) { 287 if (comparer == null) 288 return a.equals(b); 289 else 290 return comparer.equals(a, b); 291 } 292 293 300 public Enumeration keys() { 301 if (elementCount == 0) 302 return emptyEnumerator; 303 return new HashEnumerator(true); 304 } 305 306 316 public Object put(Object key, Object value) { 317 if (key != null && value != null) { 318 int index= (hashCode(key) & 0x7FFFFFFF) % elementData.length; 319 HashMapEntry entry= elementData[index]; 320 while (entry != null && ! keyEquals(key, entry.key)) 321 entry= entry.next; 322 if (entry == null) { 323 if (++elementCount > threshold) { 324 rehash(); 325 index= (hashCode(key) & 0x7FFFFFFF) % elementData.length; 326 } 327 if (index < firstSlot) 328 firstSlot= index; 329 if (index > lastSlot) 330 lastSlot= index; 331 entry= new HashMapEntry(key, value); 332 entry.next= elementData[index]; 333 elementData[index]= entry; 334 return null; 335 } 336 Object result= entry.value; 337 entry.key= key; entry.value= value; 340 return result; 341 } else 342 throw new NullPointerException (); 343 } 344 345 349 private void rehash() { 350 int length= elementData.length << 1; 351 if (length == 0) 352 length= 1; 353 firstSlot= length; 354 lastSlot= - 1; 355 HashMapEntry[] newData= new HashMapEntry[length]; 356 for (int i= elementData.length; --i >= 0;) { 357 HashMapEntry entry= elementData[i]; 358 while (entry != null) { 359 int index= (hashCode(entry.key) & 0x7FFFFFFF) % length; 360 if (index < firstSlot) 361 firstSlot= index; 362 if (index > lastSlot) 363 lastSlot= index; 364 HashMapEntry next= entry.next; 365 entry.next= newData[index]; 366 newData[index]= entry; 367 entry= next; 368 } 369 } 370 elementData= newData; 371 computeMaxSize(); 372 } 373 374 381 public Object remove(Object key) { 382 HashMapEntry last= null; 383 int index= (hashCode(key) & 0x7FFFFFFF) % elementData.length; 384 HashMapEntry entry= elementData[index]; 385 while (entry != null && ! keyEquals(key, entry.key)) { 386 last= entry; 387 entry= entry.next; 388 } 389 if (entry != null) { 390 if (last == null) 391 elementData[index]= entry.next; 392 else 393 last.next= entry.next; 394 elementCount--; 395 return entry.value; 396 } 397 return null; 398 } 399 400 405 public int size() { 406 return elementCount; 407 } 408 409 414 public String toString() { 415 if (size() == 0) 416 return "{}"; 418 StringBuffer buffer= new StringBuffer (); 419 buffer.append('{'); 420 for (int i= elementData.length; --i >= 0;) { 421 HashMapEntry entry= elementData[i]; 422 if (entry != null) 423 entry.appendToStringWithCommaNL(buffer); 424 } 425 if (elementCount > 0) 427 buffer.setLength(buffer.length() - 2); 428 buffer.append('}'); 429 return buffer.toString(); 430 } 431 } 432 | Popular Tags |