1 23 24 package org.apache.slide.util; 25 26 27 34 public class HashMap { 35 36 39 public static final int DEFAULT_SIZE = 17; 40 41 44 private Bucket[] table = null; 45 46 private int elementCount = 0; 47 48 51 public HashMap() { 52 this(HashMap.DEFAULT_SIZE); 53 } 55 67 public HashMap(int size) { 68 super(); 69 if (size <= 0) size = DEFAULT_SIZE; 71 table = new Bucket[size]; 73 for (int i = 0; i < size; i++) 74 table[i] = new Bucket(); 75 76 } 78 81 public void clear() { 82 for (int i = 0; i < table.length; i++) { 83 table[i].size = 0; 84 table[i].entry = null; 85 } 86 elementCount = 0; 87 } 89 93 public boolean containsKey(Object key) { 94 if (elementCount == 0) return false; 95 else return (findEntry(key) != null); 96 } 98 108 public boolean containsValue(Object value) { 109 110 if (elementCount == 0) return false; 111 112 boolean nullValue = (value == null); 113 114 for (int i = 0; i < table.length; i++) { 115 Entry entry = table[i].entry; 116 117 while (entry != null) { 118 if (nullValue) { 119 if (entry.getValue() == null) return true; 120 } 121 else { 122 if (value.equals(entry.getValue())) return true; 123 } 124 entry = entry.next; 125 } 126 } 127 128 return false; 129 130 } 132 133 142 public Iterator entries() { 143 return new HashMapEntryIterator(table); 144 } 146 155 public boolean equals(Object object) { 156 157 if (object == this) return true; 158 159 if (object instanceof HashMap) { 160 HashMap map = (HashMap) object; 161 if (map.size() != size()) return false; 162 Iterator iter = map.entries(); 163 while (iter.hasNext()) { 164 Entry entry = (Entry)iter.next(); 165 if (!entry.equals(findEntry(entry.getKey()))) 166 return false; 167 } 168 return true; 169 } 170 return false; 171 } 173 177 public Object get(Object key) { 178 Entry entry = findEntry(key); 179 if (entry != null) { 180 return entry.getValue(); 181 } 182 return null; 183 } 185 189 public int hashCode() { 190 int value = 0; 191 for (int i = 0; i < table.length; i++) { 192 Entry entry = table[i].entry; 193 while (entry != null) { 194 value += entry.hashCode(); 195 entry = entry.next; 196 } 197 } 198 return value; 199 } 201 205 public boolean isEmpty() { 206 return (elementCount == 0); 207 } 209 public Iterator keys() { 210 return new HashMapKeyIterator(table); 211 } 213 218 public void put(Object key, Object value) { 219 Entry entry = findEntry(key); 220 if (entry == null) 221 addEntry(key, value); 222 else 223 entry.setValue(value); 224 } 226 231 public Object remove(Object key) { 232 233 if (elementCount == 0) return null; 234 235 int hash = hashCode(key); 236 237 Bucket bucket = table[hash % table.length]; 238 239 Entry entry = bucket.entry; 240 241 boolean nullKey = (key == null); 242 243 while (entry != null) { 244 245 if (nullKey) { 246 if (entry.getKey() == null) break; } 248 else if (hash < entry.hash) 249 return null; else { 251 if (entry.getKey().equals(key)) break; } 253 entry = entry.next; 254 } 255 256 Object value = null; 257 258 if (entry != null) { 259 260 if (entry.prev != null) 261 entry.prev.next = entry.next; 262 else 263 bucket.entry = entry.next; 264 265 if (entry.next != null) 266 entry.next.prev = entry.prev; 267 268 value = entry.getValue(); 269 --bucket.size; 270 --elementCount; 271 } 272 273 return value; 274 } 276 280 public int size() { 281 return elementCount; 282 } 284 288 private int hashCode(Object key) { 289 int hash = (key == null) ? 0 : key.hashCode(); 290 if (hash < 0) hash = -hash; 291 return hash; 292 } 294 300 private void addEntry(Object key, Object value) { 301 302 int hash = hashCode(key); 304 305 Entry newEntry = new Entry(hash, key, value); 306 307 Bucket bucket = table[hash % table.length]; 308 309 if (bucket.entry == null) bucket.entry = newEntry; 310 else { 311 Entry current = bucket.entry; 313 while (current != null) { 314 if (hash <= current.hash) { 315 if (current.prev != null) { 317 current.prev.next = newEntry; 319 newEntry.prev = current.prev; 320 } 321 else bucket.entry = newEntry; 323 newEntry.next = current; 325 break; 326 } 327 else if (current.next == null) { 328 current.next = newEntry; 331 newEntry.prev = current; 332 break; 333 } 334 current = current.next; 335 } 336 } 337 338 ++bucket.size; 339 ++elementCount; 340 } 342 346 private Entry findEntry(Object key) { 347 if (elementCount == 0) return null; 348 return findEntry(key, hashCode(key)); 349 } 351 357 private Entry findEntry(Object key, int hash) { 358 359 if (elementCount == 0) return null; 360 361 int index = hash % table.length; 362 363 Entry entry = table[index].entry; 364 365 boolean nullKey = (key == null); 366 367 while (entry != null) { 368 369 if (nullKey) { 370 if (entry.getKey() == null) 371 return entry; 372 } 373 else if (hash == entry.hash) { 374 if (entry.getKey().equals(key)) 375 return entry; 376 } 377 else if (hash < entry.hash) break; 379 entry = entry.next; 380 } 381 382 return null; 383 } 385 386 390 393 class Bucket { 394 int size = 0; 395 Entry entry = null; 396 } 398 401 class Entry { 402 403 int hash = 0; 404 405 Object key = null; 406 Object value = null; 407 408 Entry next = null; 409 Entry prev = null; 410 411 public Entry(int hashCode, Object key, Object value) { 412 this.hash = hashCode; 413 this.key = key; 414 this.value = value; 415 } 417 public Object getKey() { 418 return key; 419 } 421 public Object getValue() { 422 return value; 423 } 425 public boolean equals(Object object) { 426 427 if (object == null) return false; 428 429 if (object instanceof Entry) { 430 431 Entry entry = (Entry) object; 432 433 if (this.key == null) 434 if (entry.getKey() != null) 435 return false; 436 else 437 if (!this.key.equals(entry.getKey())) 438 return false; 439 440 if (this.value == null) 441 return (entry.getValue() == null); 442 else 443 return (this.value.equals(entry.getValue())); 444 } 445 446 return false; 447 } 449 public int hashCode() { 450 int keyHash = (key == null) ? 0 : key.hashCode(); 451 int valHash = (value == null) ? 0 : value.hashCode(); 452 return (keyHash ^ valHash); 453 } 455 public void setValue(Object value) { 456 this.value = value; 457 } } 460 } 462 class HashMapEntryIterator implements Iterator { 463 464 HashMap.Bucket[] table = null; 465 private int index = 0; 466 private HashMap.Entry current = null; 467 private HashMap.Entry next = null; 468 469 HashMapEntryIterator(HashMap.Bucket[] table) { 470 471 System.out.println("<HashMapEntryIterator>"); 472 this.table = table; 473 while (index < table.length) { 475 next = table[index].entry; 476 if (next != null) break; 477 ++index; 478 } 479 480 System.out.println("</HashMapEntryIterator>"); 481 } 483 public boolean hasNext() { 484 return (next != null); 485 } 487 public Object next() { 488 current = next; 489 if (next == null) return null; 490 next = next.next; 491 if (next == null) { 492 while (++index < table.length) { 494 next = table[index].entry; 495 if (next != null) break; 496 } 497 } 498 return current; 499 } 501 public Object remove() { 502 throw new IllegalStateException ("#remove() is not yet implemented"); 504 } 506 } 508 class HashMapKeyIterator extends HashMapEntryIterator { 509 510 HashMapKeyIterator(HashMap.Bucket[] table) { 511 super(table); 512 } 514 public Object next() { 515 HashMap.Entry entry = (HashMap.Entry)super.next(); 516 if (entry != null) return entry.getKey(); 517 return null; 518 } 520 } | Popular Tags |