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 if (lastReturnedIndex < 0) 864 return super.hashCode(); 865 866 return System.identityHashCode(getKey()) ^ 867 System.identityHashCode(getValue()); 868 } 869 870 public String toString() { 871 if (lastReturnedIndex < 0) 872 return super.toString(); 873 874 return getKey() + "=" + getValue(); 875 } 876 } 877 878 880 885 886 private transient Set <Map.Entry <K,V>> entrySet = null; 887 888 926 public Set <K> keySet() { 927 Set <K> ks = keySet; 928 if (ks != null) 929 return ks; 930 else 931 return keySet = new KeySet(); 932 } 933 934 private class KeySet extends AbstractSet <K> { 935 public Iterator <K> iterator() { 936 return new KeyIterator(); 937 } 938 public int size() { 939 return size; 940 } 941 public boolean contains(Object o) { 942 return containsKey(o); 943 } 944 public boolean remove(Object o) { 945 int oldSize = size; 946 IdentityHashMap.this.remove(o); 947 return size != oldSize; 948 } 949 954 public boolean removeAll(Collection <?> c) { 955 boolean modified = false; 956 for (Iterator i = iterator(); i.hasNext(); ) { 957 if (c.contains(i.next())) { 958 i.remove(); 959 modified = true; 960 } 961 } 962 return modified; 963 } 964 public void clear() { 965 IdentityHashMap.this.clear(); 966 } 967 public int hashCode() { 968 int result = 0; 969 for (K key : this) 970 result += System.identityHashCode(key); 971 return result; 972 } 973 } 974 975 996 public Collection <V> values() { 997 Collection <V> vs = values; 998 if (vs != null) 999 return vs; 1000 else 1001 return values = new Values(); 1002 } 1003 1004 private class Values extends AbstractCollection <V> { 1005 public Iterator <V> iterator() { 1006 return new ValueIterator(); 1007 } 1008 public int size() { 1009 return size; 1010 } 1011 public boolean contains(Object o) { 1012 return containsValue(o); 1013 } 1014 public boolean remove(Object o) { 1015 for (Iterator i = iterator(); i.hasNext(); ) { 1016 if (i.next() == o) { 1017 i.remove(); 1018 return true; 1019 } 1020 } 1021 return false; 1022 } 1023 public void clear() { 1024 IdentityHashMap.this.clear(); 1025 } 1026 } 1027 1028 1065 public Set <Map.Entry <K,V>> entrySet() { 1066 Set <Map.Entry <K,V>> es = entrySet; 1067 if (es != null) 1068 return es; 1069 else 1070 return entrySet = new EntrySet(); 1071 } 1072 1073 private class EntrySet extends AbstractSet <Map.Entry <K,V>> { 1074 public Iterator <Map.Entry <K,V>> iterator() { 1075 return new EntryIterator(); 1076 } 1077 public boolean contains(Object o) { 1078 if (!(o instanceof Map.Entry )) 1079 return false; 1080 Map.Entry entry = (Map.Entry )o; 1081 return containsMapping(entry.getKey(), entry.getValue()); 1082 } 1083 public boolean remove(Object o) { 1084 if (!(o instanceof Map.Entry )) 1085 return false; 1086 Map.Entry entry = (Map.Entry )o; 1087 return removeMapping(entry.getKey(), entry.getValue()); 1088 } 1089 public int size() { 1090 return size; 1091 } 1092 public void clear() { 1093 IdentityHashMap.this.clear(); 1094 } 1095 1100 public boolean removeAll(Collection <?> c) { 1101 boolean modified = false; 1102 for (Iterator i = iterator(); i.hasNext(); ) { 1103 if(c.contains(i.next())) { 1104 i.remove(); 1105 modified = true; 1106 } 1107 } 1108 return modified; 1109 } 1110 1111 public Object [] toArray() { 1112 List <Map.Entry <K,V>> c = new ArrayList <Map.Entry <K,V>>(size()); 1113 for (Map.Entry <K,V> e : this) 1114 c.add(new AbstractMap.SimpleEntry <K,V>(e)); 1115 return c.toArray(); 1116 } 1117 public <T> T[] toArray(T[] a) { 1118 int size = size(); 1119 if (a.length < size) 1120 a = (T[])java.lang.reflect.Array 1121 .newInstance(a.getClass().getComponentType(), size); 1122 Iterator <Map.Entry <K,V>> it = iterator(); 1123 for (int i = 0; i < size; i++) 1124 a[i] = (T) new AbstractMap.SimpleEntry <K,V>(it.next()); 1125 if (a.length > size) 1126 a[size] = null; 1127 return a; 1128 } 1129 } 1130 1131 1132 private static final long serialVersionUID = 8188218128353913216L; 1133 1134 1144 private void writeObject(java.io.ObjectOutputStream s) 1145 throws java.io.IOException { 1146 s.defaultWriteObject(); 1148 1149 s.writeInt(size); 1151 1152 Object [] tab = table; 1154 for (int i = 0; i < tab.length; i += 2) { 1155 Object key = tab[i]; 1156 if (key != null) { 1157 s.writeObject(unmaskNull(key)); 1158 s.writeObject(tab[i + 1]); 1159 } 1160 } 1161 } 1162 1163 1167 private void readObject(java.io.ObjectInputStream s) 1168 throws java.io.IOException , ClassNotFoundException { 1169 s.defaultReadObject(); 1171 1172 int size = s.readInt(); 1174 1175 init(capacity((size*4)/3)); 1177 1178 for (int i=0; i<size; i++) { 1180 K key = (K) s.readObject(); 1181 V value = (V) s.readObject(); 1182 putForCreate(key, value); 1183 } 1184 } 1185 1186 1190 private void putForCreate(K key, V value) 1191 throws IOException 1192 { 1193 K k = (K)maskNull(key); 1194 Object [] tab = table; 1195 int len = tab.length; 1196 int i = hash(k, len); 1197 1198 Object item; 1199 while ( (item = tab[i]) != null) { 1200 if (item == k) 1201 throw new java.io.StreamCorruptedException (); 1202 i = nextKeyIndex(i, len); 1203 } 1204 tab[i] = k; 1205 tab[i + 1] = value; 1206 } 1207} 1208 | Popular Tags |