| 1 52 53 package com.go.trove.util; 54 55 import java.util.*; 56 import java.io.*; 57 58 67 public class IntHashMap extends AbstractMap 68 implements Map, Cloneable , Serializable { 69 70 73 private transient Entry table[]; 74 75 78 private transient int count; 79 80 86 private int threshold; 87 88 93 private float loadFactor; 94 95 102 private transient int modCount = 0; 103 104 113 public IntHashMap(int initialCapacity, float loadFactor) { 114 if (initialCapacity < 0) { 115 throw new IllegalArgumentException ("Illegal Initial Capacity: "+ 116 initialCapacity); 117 } 118 119 if (loadFactor <= 0) { 120 throw new IllegalArgumentException ("Illegal Load factor: "+ 121 loadFactor); 122 } 123 124 if (initialCapacity==0) { 125 initialCapacity = 1; 126 } 127 128 this.loadFactor = loadFactor; 129 table = new Entry[initialCapacity]; 130 threshold = (int)(initialCapacity * loadFactor); 131 } 132 133 141 public IntHashMap(int initialCapacity) { 142 this(initialCapacity, 0.75f); 143 } 144 145 149 public IntHashMap() { 150 this(101, 0.75f); 151 } 152 153 159 public IntHashMap(Map t) { 160 this(Math.max(2*t.size(), 11), 0.75f); 161 putAll(t); 162 } 163 164 169 public int size() { 170 return count; 171 } 172 173 178 public boolean isEmpty() { 179 return count == 0; 180 } 181 182 190 public boolean containsValue(Object value) { 191 Entry tab[] = table; 192 193 if (value==null) { 194 for (int i = tab.length ; i-- > 0 ;) { 195 for (Entry e = tab[i] ; e != null ; e = e.next) { 196 if (e.value == null) { 197 return true; 198 } 199 } 200 } 201 } 202 else { 203 for (int i = tab.length ; i-- > 0 ;) { 204 for (Entry e = tab[i] ; e != null ; e = e.next) { 205 if (value.equals(e.value)) { 206 return true; 207 } 208 } 209 } 210 } 211 212 return false; 213 } 214 215 223 public boolean containsKey(Object key) { 224 if (key instanceof Number ) { 225 return containsKey( ((Number )key).intValue() ); 226 } 227 else { 228 return false; 229 } 230 } 231 232 240 public boolean containsKey(int key) { 241 Entry tab[] = table; 242 243 int index = (key & 0x7FFFFFFF) % tab.length; 244 for (Entry e = tab[index]; e != null; e = e.next) { 245 if (e.key == key) { 246 return true; 247 } 248 } 249 250 return false; 251 } 252 253 264 public Object get(Object key) { 265 if (key instanceof Number ) { 266 return get( ((Number )key).intValue() ); 267 } 268 else { 269 return null; 270 } 271 } 272 273 284 public Object get(int key) { 285 Entry tab[] = table; 286 287 int index = (key & 0x7FFFFFFF) % tab.length; 288 for (Entry e = tab[index]; e != null; e = e.next) { 289 if (e.key == key) { 290 return e.value; 291 } 292 } 293 294 return null; 295 } 296 297 302 private void rehash() { 303 int oldCapacity = table.length; 304 Entry oldMap[] = table; 305 306 int newCapacity = oldCapacity * 2 + 1; 307 Entry newMap[] = new Entry[newCapacity]; 308 309 modCount++; 310 threshold = (int)(newCapacity * loadFactor); 311 table = newMap; 312 313 for (int i = oldCapacity ; i-- > 0 ;) { 314 for (Entry old = oldMap[i] ; old != null ; ) { 315 Entry e = old; 316 old = old.next; 317 318 int index = (e.key & 0x7FFFFFFF) % newCapacity; 319 e.next = newMap[index]; 320 newMap[index] = e; 321 } 322 } 323 } 324 325 337 public Object put(Object key, Object value) { 338 if (key instanceof Number ) { 339 return put( ((Number )key).intValue(), value ); 340 } 341 else { 342 throw new UnsupportedOperationException  343 ("IntHashMap key must be a number"); 344 } 345 } 346 347 359 public Object put(int key, Object value) { 360 Entry tab[] = table; 362 int index = 0; 363 364 index = (key & 0x7FFFFFFF) % tab.length; 365 for (Entry e = tab[index] ; e != null ; e = e.next) { 366 if (e.key == key) { 367 Object old = e.value; 368 e.value = value; 369 return old; 370 } 371 } 372 373 modCount++; 374 if (count >= threshold) { 375 rehash(); 377 378 tab = table; 379 index = (key & 0x7FFFFFFF) % tab.length; 380 } 381 382 Entry e = new Entry(key, value, tab[index]); 384 tab[index] = e; 385 count++; 386 return null; 387 } 388 389 398 public Object remove(Object key) { 399 if (key instanceof Number ) { 400 return remove( ((Number )key).intValue() ); 401 } 402 else { 403 return null; 404 } 405 } 406 407 416 public Object remove(int key) { 417 Entry tab[] = table; 418 419 int index = (key & 0x7FFFFFFF) % tab.length; 420 421 for (Entry e = tab[index], prev = null; e != null; 422 prev = e, e = e.next) { 423 424 if (e.key == key) { 425 modCount++; 426 if (prev != null) { 427 prev.next = e.next; 428 } 429 else { 430 tab[index] = e.next; 431 } 432 433 count--; 434 Object oldValue = e.value; 435 e.value = null; 436 return oldValue; 437 } 438 } 439 440 return null; 441 } 442 443 451 public void putAll(Map t) { 452 Iterator i = t.entrySet().iterator(); 453 while (i.hasNext()) { 454 Map.Entry e = (Map.Entry) i.next(); 455 put(e.getKey(), e.getValue()); 456 } 457 } 458 459 462 public void clear() { 463 Entry tab[] = table; 464 modCount++; 465 for (int index = tab.length; --index >= 0; ) { 466 tab[index] = null; 467 } 468 count = 0; 469 } 470 471 477 public Object clone() { 478 try { 479 IntHashMap t = (IntHashMap)super.clone(); 480 t.table = new Entry[table.length]; 481 for (int i = table.length ; i-- > 0 ; ) { 482 t.table[i] = (table[i] != null) 483 ? (Entry)table[i].clone() : null; 484 } 485 t.keySet = null; 486 t.entrySet = null; 487 t.values = null; 488 t.modCount = 0; 489 return t; 490 } 491 catch (CloneNotSupportedException e) { 492 throw new InternalError (); 494 } 495 } 496 497 499 private transient Set keySet = null; 500 private transient Set entrySet = null; 501 private transient Collection values = null; 502 503 514 public Set keySet() { 515 if (keySet == null) { 516 keySet = new AbstractSet() { 517 public Iterator iterator() { 518 return new IntHashIterator(KEYS); 519 } 520 public int size() { 521 return count; 522 } 523 public boolean contains(Object o) { 524 return containsKey(o); 525 } 526 public boolean remove(Object o) { 527 return IntHashMap.this.remove(o) != null; 528 } 529 public void clear() { 530 IntHashMap.this.clear(); 531 } 532 }; 533 } 534 return keySet; 535 } 536 537 548 public Collection values() { 549 if (values==null) { 550 values = new AbstractCollection() { 551 public Iterator iterator() { 552 return new IntHashIterator(VALUES); 553 } 554 public int size() { 555 return count; 556 } 557 public boolean contains(Object o) { 558 return containsValue(o); 559 } 560 public void clear() { 561 IntHashMap.this.clear(); 562 } 563 }; 564 } 565 return values; 566 } 567 568 581 public Set entrySet() { 582 if (entrySet==null) { 583 entrySet = new AbstractSet() { 584 public Iterator iterator() { 585 return new IntHashIterator(ENTRIES); 586 } 587 588 public boolean contains(Object o) { 589 if (!(o instanceof Map.Entry)) { 590 return false; 591 } 592 Map.Entry entry = (Map.Entry)o; 593 Object key = entry.getKey(); 594 Entry tab[] = table; 595 int hash = (key==null ? 0 : key.hashCode()); 596 int index = (hash & 0x7FFFFFFF) % tab.length; 597 598 for (Entry e = tab[index]; e != null; e = e.next) { 599 if (e.key == hash && e.equals(entry)) { 600 return true; 601 } 602 } 603 return false; 604 } 605 606 public boolean remove(Object o) { 607 if (!(o instanceof Map.Entry)) 608 return false; 609 Map.Entry entry = (Map.Entry)o; 610 Object key = entry.getKey(); 611 Entry tab[] = table; 612 int hash = (key==null ? 0 : key.hashCode()); 613 int index = (hash & 0x7FFFFFFF) % tab.length; 614 615 for (Entry e = tab[index], prev = null; e != null; 616 prev = e, e = e.next) { 617 if (e.key == hash && e.equals(entry)) { 618 modCount++; 619 if (prev != null) { 620 prev.next = e.next; 621 } 622 else { 623 tab[index] = e.next; 624 } 625 626 count--; 627 e.value = null; 628 return true; 629 } 630 } 631 return false; 632 } 633 634 public int size() { 635 return count; 636 } 637 638 public void clear() { 639 IntHashMap.this.clear(); 640 } 641 }; 642 } 643 644 return entrySet; 645 } 646 647 650 private static class Entry implements Map.Entry { 651 int key; 652 Object value; 653 Entry next; 654 private Integer objectKey; 655 656 Entry(int key, Object value, Entry next) { 657 this.key = key; 658 this.value = value; 659 this.next = next; 660 } 661 662 protected Object clone() { 663 return new Entry(key, value, 664 (next==null ? null : (Entry)next.clone())); 665 } 666 667 669 public Object getKey() { 670 return (objectKey != null) ? objectKey : 671 (objectKey = new Integer (key)); 672 } 673 674 public Object getValue() { 675 return value; 676 } 677 678 public Object setValue(Object value) { 679 Object oldValue = this.value; 680 this.value = value; 681 return oldValue; 682 } 683 684 public boolean equals(Object o) { 685 if (!(o instanceof Map.Entry)) { 686 return false; 687 } 688 Map.Entry e = (Map.Entry)o; 689 690 return (getKey().equals(e.getKey())) && 691 (value==null ? e.getValue()==null : value.equals(e.getValue())); 692 } 693 694 public int hashCode() { 695 return key ^ (value==null ? 0 : value.hashCode()); 696 } 697 698 public String toString() { 699 return String.valueOf(key) + "=" + value; 700 } 701 } 702 703 private static final int KEYS = 0; 705 private static final int VALUES = 1; 706 private static final int ENTRIES = 2; 707 708 private class IntHashIterator implements Iterator { 709 Entry[] table = IntHashMap.this.table; 710 int index = table.length; 711 Entry entry = null; 712 Entry lastReturned = null; 713 int type; 714 715 720 private int expectedModCount = modCount; 721 722 IntHashIterator(int type) { 723 this.type = type; 724 } 725 726 public boolean hasNext() { 727 while (entry == null && index > 0) { 728 entry = table[--index]; 729 } 730 731 return entry != null; 732 } 733 734 public Object next() { 735 if (modCount != expectedModCount) { 736 throw new ConcurrentModificationException(); 737 } 738 739 while (entry == null && index > 0) { 740 entry = table[--index]; 741 } 742 743 if (entry != null) { 744 Entry e = lastReturned = entry; 745 entry = e.next; 746 return type == KEYS ? e.getKey() : 747 (type == VALUES ? e.value : e); 748 } 749 throw new NoSuchElementException(); 750 } 751 752 public void remove() { 753 if (lastReturned == null) { 754 throw new IllegalStateException (); 755 } 756 if (modCount != expectedModCount) { 757 throw new ConcurrentModificationException(); 758 } 759 760 Entry[] tab = IntHashMap.this.table; 761 int index = (lastReturned.key & 0x7FFFFFFF) % tab.length; 762 763 for (Entry e = tab[index], prev = null; e != null; 764 prev = e, e = e.next) { 765 if (e == lastReturned) { 766 modCount++; 767 expectedModCount++; 768 if (prev == null) { 769 tab[index] = e.next; 770 } 771 else { 772 prev.next = e.next; 773 } 774 count--; 775 lastReturned = null; 776 return; 777 } 778 } 779 throw new ConcurrentModificationException(); 780 } 781 } 782 783 794 private void writeObject(java.io.ObjectOutputStream s) 795 throws IOException 796 { 797 s.defaultWriteObject(); 799 800 s.writeInt(table.length); 802 803 s.writeInt(count); 805 806 for (int index = table.length-1; index >= 0; index--) { 808 Entry entry = table[index]; 809 810 while (entry != null) { 811 s.writeInt(entry.key); 812 s.writeObject(entry.value); 813 entry = entry.next; 814 } 815 } 816 } 817 818 822 private void readObject(java.io.ObjectInputStream s) 823 throws IOException, ClassNotFoundException  824 { 825 s.defaultReadObject(); 827 828 int numBuckets = s.readInt(); 830 table = new Entry[numBuckets]; 831 832 int size = s.readInt(); 834 835 for (int i=0; i<size; i++) { 837 int key = s.readInt(); 838 Object value = s.readObject(); 839 put(key, value); 840 } 841 } 842 843 int capacity() { 844 return table.length; 845 } 846 847 float loadFactor() { 848 return loadFactor; 849 } 850 } 851 | Popular Tags |