| 1 7 8 package java.util; 9 10 import java.io.*; 11 12 114 115 public class IdentityHashMap<K,V> 116 extends AbstractMap <K,V> 117 implements Map <K,V>, java.io.Serializable , Cloneable  118 { 119 125 private static final int DEFAULT_CAPACITY = 32; 126 127 133 private static final int MINIMUM_CAPACITY = 4; 134 135 140 private static final int MAXIMUM_CAPACITY = 1 << 29; 141 142 145 private transient Object [] table; 146 147 152 private int size; 153 154 157 private transient volatile int modCount; 158 159 162 private transient int threshold; 163 164 167 private static final Object NULL_KEY = new Object (); 168 169 172 173 private static Object maskNull(Object key) { 174 return (key == null ? NULL_KEY : key); 175 } 176 177 180 private static Object unmaskNull(Object key) { 181 return (key == NULL_KEY ? null : key); 182 } 183 184 188 public IdentityHashMap() { 189 init(DEFAULT_CAPACITY); 190 } 191 192 201 public IdentityHashMap(int expectedMaxSize) { 202 if (expectedMaxSize < 0) 203 throw new IllegalArgumentException ("expectedMaxSize is negative: " 204 + expectedMaxSize); 205 init(capacity(expectedMaxSize)); 206 } 207 208 216 private int capacity(int expectedMaxSize) { 217 int minCapacity = (3 * expectedMaxSize)/2; 219 220 int result; 222 if (minCapacity > MAXIMUM_CAPACITY || minCapacity < 0) { 223 result = MAXIMUM_CAPACITY; 224 } else { 225 result = MINIMUM_CAPACITY; 226 while (result < minCapacity) 227 result <<= 1; 228 } 229 return result; 230 } 231 232 237 private void init(int initCapacity) { 238 242 threshold = (initCapacity * 2)/3; 243 table = new Object [2 * initCapacity]; 244 } 245 246 253 public IdentityHashMap(Map <? extends K, ? extends V> m) { 254 this((int) ((1 + m.size()) * 1.1)); 256 putAll(m); 257 } 258 259 264 public int size() { 265 return size; 266 } 267 268 275 public boolean isEmpty() { 276 return size == 0; 277 } 278 279 282 private static int hash(Object x, int length) { 283 int h = System.identityHashCode(x); 284 return ((h << 1) - (h << 8)) & (length - 1); 286 } 287 288 291 private static int nextKeyIndex(int i, int len) { 292 return (i + 2 < len ? i + 2 : 0); 293 } 294 295 309 public V get(Object key) { 310 Object k = maskNull(key); 311 Object [] tab = table; 312 int len = tab.length; 313 int i = hash(k, len); 314 while (true) { 315 Object item = tab[i]; 316 if (item == k) 317 return (V) tab[i + 1]; 318 if (item == null) 319 return null; 320 i = nextKeyIndex(i, len); 321 } 322 } 323 324 333 public boolean containsKey(Object key) { 334 Object k = maskNull(key); 335 Object [] tab = table; 336 int len = tab.length; 337 int i = hash(k, len); 338 while (true) { 339 Object item = tab[i]; 340 if (item == k) 341 return true; 342 if (item == null) 343 return false; 344 i = nextKeyIndex(i, len); 345 } 346 } 347 348 357 public boolean containsValue(Object value) { 358 Object [] tab = table; 359 for (int i = 1; i < tab.length; i+= 2) 360 if (tab[i] == value) 361 return true; 362 363 return false; 364 } 365 366 374 private boolean containsMapping(Object key, Object value) { 375 Object k = maskNull(key); 376 Object [] tab = table; 377 int len = tab.length; 378 int i = hash(k, len); 379 while (true) { 380 Object item = tab[i]; 381 if (item == k) 382 return tab[i + 1] == value; 383 if (item == null) 384 return false; 385 i = nextKeyIndex(i, len); 386 } 387 } 388 389 404 public V put(K key, V value) { 405 Object k = maskNull(key); 406 Object [] tab = table; 407 int len = tab.length; 408 int i = hash(k, len); 409 410 Object item; 411 while ( (item = tab[i]) != null) { 412 if (item == k) { 413 V oldValue = (V) tab[i + 1]; 414 tab[i + 1] = value; 415 return oldValue; 416 } 417 i = nextKeyIndex(i, len); 418 } 419 420 modCount++; 421 tab[i] = k; 422 tab[i + 1] = value; 423 if (++size >= threshold) 424 resize(len); return null; 426 } 427 428 433 private void resize(int newCapacity) { 434 int newLength = newCapacity * 2; 436 437 Object [] oldTable = table; 438 int oldLength = oldTable.length; 439 if (oldLength == 2*MAXIMUM_CAPACITY) { if (threshold == MAXIMUM_CAPACITY-1) 441 throw new IllegalStateException ("Capacity exhausted."); 442 threshold = MAXIMUM_CAPACITY-1; return; 444 } 445 if (oldLength >= newLength) 446 return; 447 448 Object [] newTable = new Object [newLength]; 449 threshold = newLength / 3; 450 451 for (int j = 0; j < oldLength; j += 2) { 452 Object key = oldTable[j]; 453 if (key != null) { 454 Object value = oldTable[j+1]; 455 oldTable[j] = null; 456 oldTable[j+1] = null; 457 int i = hash(key, newLength); 458 while (newTable[i] != null) 459 i = nextKeyIndex(i, newLength); 460 newTable[i] = key; 461 newTable[i + 1] = value; 462 } 463 } 464 table = newTable; 465 } 466 467 475 public void putAll(Map <? extends K, ? extends V> t) { 476 int n = t.size(); 477 if (n == 0) 478 return; 479 if (n > threshold) resize(capacity(n)); 481 482 for (Entry<? extends K, ? extends V> e : t.entrySet()) 483 put(e.getKey(), e.getValue()); 484 } 485 486 495 public V remove(Object key) { 496 Object k = maskNull(key); 497 Object [] tab = table; 498 int len = tab.length; 499 int i = hash(k, len); 500 501 while (true) { 502 Object item = tab[i]; 503 if (item == k) { 504 modCount++; 505 size--; 506 V oldValue = (V) tab[i + 1]; 507 tab[i + 1] = null; 508 tab[i] = null; 509 closeDeletion(i); 510 return oldValue; 511 } 512 if (item == null) 513 return null; 514 i = nextKeyIndex(i, len); 515 } 516 517 } 518 519 527 private boolean removeMapping(Object key, Object value) { 528 Object k = maskNull(key); 529 Object [] tab = table; 530 int len = tab.length; 531 int i = hash(k, len); 532 533 while (true) { 534 Object item = tab[i]; 535 if (item == k) { 536 if (tab[i + 1] != value) 537 return false; 538 modCount++; 539 size--; 540 tab[i] = null; 541 tab[i + 1] = null; 542 closeDeletion(i); 543 return true; 544 } 545 if (item == null) 546 return false; 547 i = nextKeyIndex(i, len); 548 } 549 } 550 551 558 private void closeDeletion(int d) { 559 Object [] tab = table; 561 int len = tab.length; 562 563 Object item; 568 for (int i = nextKeyIndex(d, len); (item = tab[i]) != null; 569 i = nextKeyIndex(i, len) ) { 570 int r = hash(item, len); 577 if ((i < r && (r <= d || d <= i)) || (r <= d && d <= i)) { 578 tab[d] = item; 579 tab[d + 1] = tab[i + 1]; 580 tab[i] = null; 581 tab[i + 1] = null; 582 d = i; 583 } 584 } 585 } 586 587 590 public void clear() { 591 modCount++; 592 Object [] tab = table; 593 for (int i = 0; i < tab.length; i++) 594 tab[i] = null; 595 size = 0; 596 } 597 598 615 public boolean equals(Object o) { 616 if (o == this) { 617 return true; 618 } else if (o instanceof IdentityHashMap ) { 619 IdentityHashMap m = (IdentityHashMap ) o; 620 if (m.size() != size) 621 return false; 622 623 Object [] tab = m.table; 624 for (int i = 0; i < tab.length; i+=2) { 625 Object k = tab[i]; 626 if (k != null && !containsMapping(k, tab[i + 1])) 627 return false; 628 } 629 return true; 630 } else if (o instanceof Map ) { 631 Map m = (Map )o; 632 return entrySet().equals(m.entrySet()); 633 } else { 634 return false; } 636 } 637 638 658 public int hashCode() { 659 int result = 0; 660 Object [] tab = table; 661 for (int i = 0; i < tab.length; i +=2) { 662 Object key = tab[i]; 663 if (key != null) { 664 Object k = unmaskNull(key); 665 result += System.identityHashCode(k) ^ 666 System.identityHashCode(tab[i + 1]); 667 } 668 } 669 return result; 670 } 671 672 678 public Object clone() { 679 try { 680 IdentityHashMap <K,V> t = (IdentityHashMap <K,V>) super.clone(); 681 t.entrySet = null; 682 t.table = (Object [])table.clone(); 683 return t; 684 } catch (CloneNotSupportedException e) { 685 throw new InternalError (); 686 } 687 } 688 689 private abstract class IdentityHashMapIterator<T> implements Iterator <T> { 690 int index = (size != 0 ? 0 : table.length); int expectedModCount = modCount; int lastReturnedIndex = -1; boolean indexValid; Object [] traversalTable = table; 696 public boolean hasNext() { 697 Object [] tab = traversalTable; 698 for (int i = index; i < tab.length; i+=2) { 699 Object key = tab[i]; 700 if (key != null) { 701 index = i; 702 return indexValid = true; 703 } 704 } 705 index = tab.length; 706 return false; 707 } 708 709 protected int nextIndex() { 710 if (modCount != expectedModCount) 711 throw new ConcurrentModificationException (); 712 if (!indexValid && !hasNext()) 713 throw new NoSuchElementException (); 714 715 indexValid = false; 716 lastReturnedIndex = index; 717 index += 2; 718 return lastReturnedIndex; 719 } 720 721 public void remove() { 722 if (lastReturnedIndex == -1) 723 throw new IllegalStateException (); 724 if (modCount != expectedModCount) 725 throw new ConcurrentModificationException (); 726 727 expectedModCount = ++modCount; 728 int deletedSlot = lastReturnedIndex; 729 lastReturnedIndex = -1; 730 size--; 731 index = deletedSlot; 733 indexValid = false; 734 735 747 Object [] tab = traversalTable; 748 int len = tab.length; 749 750 int d = deletedSlot; 751 K key = (K) tab[d]; 752 tab[d] = null; tab[d + 1] = null; 754 755 if (tab != IdentityHashMap.this.table) { 758 IdentityHashMap.this.remove(key); 759 expectedModCount = modCount; 760 return; 761 } 762 763 Object item; 764 for (int i = nextKeyIndex(d, len); (item = tab[i]) != null; 765 i = nextKeyIndex(i, len)) { 766 int r = hash(item, len); 767 if ((i < r && (r <= d || d <= i)) || 769 (r <= d && d <= i)) { 770 771 778 if (i < deletedSlot && d >= deletedSlot && 779 traversalTable == IdentityHashMap.this.table) { 780 int remaining = len - deletedSlot; 781 Object [] newTable = new Object [remaining]; 782 System.arraycopy(tab, deletedSlot, 783 newTable, 0, remaining); 784 traversalTable = newTable; 785 index = 0; 786 } 787 788 tab[d] = item; 789 tab[d + 1] = tab[i + 1]; 790 tab[i] = null; 791 tab[i + 1] = null; 792 d = i; 793 } 794 } 795 } 796 } 797 798 private class KeyIterator extends IdentityHashMapIterator<K> { 799 public K next() { 800 return (K) unmaskNull(traversalTable[nextIndex()]); 801 } 802 } 803 804 private class ValueIterator extends IdentityHashMapIterator<V> { 805 public V next() { 806 return (V) traversalTable[nextIndex() + 1]; 807 } 808 } 809 810 814 private class EntryIterator 815 extends IdentityHashMapIterator<Map.Entry <K,V>> 816 implements Map.Entry <K,V> 817 { 818 public Map.Entry <K,V> next() { 819 nextIndex(); 820 return this; 821 } 822 823 public K getKey() { 824 if (lastReturnedIndex < 0) 826 throw new IllegalStateException ("Entry was removed"); 827 828 return (K) unmaskNull(traversalTable[lastReturnedIndex]); 829 } 830 831 public V getValue() { 832 if (lastReturnedIndex < 0) 834 throw new IllegalStateException ("Entry was removed"); 835 836 return (V) traversalTable[lastReturnedIndex+1]; 837 } 838 839 public V setValue(V value) { 840 if (lastReturnedIndex < 0) 842 throw new IllegalStateException ("Entry was removed"); 843 V oldValue = (V) traversalTable[lastReturnedIndex+1]; 844 traversalTable[lastReturnedIndex+1] = value; 845 if (traversalTable != IdentityHashMap.this.table) 847 put((K) traversalTable[lastReturnedIndex], value); 848 return oldValue; 849 } 850 851 public boolean equals(Object o) { 852 if (lastReturnedIndex < 0) 853 return super.equals(o); 854 855 if (!(o instanceof Map.Entry )) 856 return false; 857 Map.Entry e = (Map.Entry )o; 858 return e.getKey() == getKey() && 859 e.getValue() == getValue(); 860 } 861 862 public int hashCode() { 863 |