127 implements Map<K,V>, Cloneable, java.io.Serializable { |
127 implements Map<K,V>, Cloneable, java.io.Serializable { |
128 |
128 |
129 /** |
129 /** |
130 * The hash table data. |
130 * The hash table data. |
131 */ |
131 */ |
132 private transient Entry[] table; |
132 private transient Entry<?,?>[] table; |
133 |
133 |
134 /** |
134 /** |
135 * The total number of entries in the hash table. |
135 * The total number of entries in the hash table. |
136 */ |
136 */ |
137 private transient int count; |
137 private transient int count; |
180 throw new IllegalArgumentException("Illegal Load: "+loadFactor); |
180 throw new IllegalArgumentException("Illegal Load: "+loadFactor); |
181 |
181 |
182 if (initialCapacity==0) |
182 if (initialCapacity==0) |
183 initialCapacity = 1; |
183 initialCapacity = 1; |
184 this.loadFactor = loadFactor; |
184 this.loadFactor = loadFactor; |
185 table = new Entry[initialCapacity]; |
185 table = new Entry<?,?>[initialCapacity]; |
186 threshold = (int)(initialCapacity * loadFactor); |
186 threshold = (int)(initialCapacity * loadFactor); |
187 } |
187 } |
188 |
188 |
189 /** |
189 /** |
190 * Constructs a new, empty hashtable with the specified initial capacity |
190 * Constructs a new, empty hashtable with the specified initial capacity |
286 public synchronized boolean contains(Object value) { |
286 public synchronized boolean contains(Object value) { |
287 if (value == null) { |
287 if (value == null) { |
288 throw new NullPointerException(); |
288 throw new NullPointerException(); |
289 } |
289 } |
290 |
290 |
291 Entry tab[] = table; |
291 Entry<?,?> tab[] = table; |
292 for (int i = tab.length ; i-- > 0 ;) { |
292 for (int i = tab.length ; i-- > 0 ;) { |
293 for (Entry<K,V> e = tab[i] ; e != null ; e = e.next) { |
293 for (Entry<?,?> e = tab[i] ; e != null ; e = e.next) { |
294 if (e.value.equals(value)) { |
294 if (e.value.equals(value)) { |
295 return true; |
295 return true; |
296 } |
296 } |
297 } |
297 } |
298 } |
298 } |
324 * <tt>equals</tt> method; <code>false</code> otherwise. |
324 * <tt>equals</tt> method; <code>false</code> otherwise. |
325 * @throws NullPointerException if the key is <code>null</code> |
325 * @throws NullPointerException if the key is <code>null</code> |
326 * @see #contains(Object) |
326 * @see #contains(Object) |
327 */ |
327 */ |
328 public synchronized boolean containsKey(Object key) { |
328 public synchronized boolean containsKey(Object key) { |
329 Entry tab[] = table; |
329 Entry<?,?> tab[] = table; |
330 int hash = key.hashCode(); |
330 int hash = key.hashCode(); |
331 int index = (hash & 0x7FFFFFFF) % tab.length; |
331 int index = (hash & 0x7FFFFFFF) % tab.length; |
332 for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) { |
332 for (Entry<?,?> e = tab[index] ; e != null ; e = e.next) { |
333 if ((e.hash == hash) && e.key.equals(key)) { |
333 if ((e.hash == hash) && e.key.equals(key)) { |
334 return true; |
334 return true; |
335 } |
335 } |
336 } |
336 } |
337 return false; |
337 return false; |
350 * @return the value to which the specified key is mapped, or |
350 * @return the value to which the specified key is mapped, or |
351 * {@code null} if this map contains no mapping for the key |
351 * {@code null} if this map contains no mapping for the key |
352 * @throws NullPointerException if the specified key is null |
352 * @throws NullPointerException if the specified key is null |
353 * @see #put(Object, Object) |
353 * @see #put(Object, Object) |
354 */ |
354 */ |
|
355 @SuppressWarnings("unchecked") |
355 public synchronized V get(Object key) { |
356 public synchronized V get(Object key) { |
356 Entry tab[] = table; |
357 Entry<?,?> tab[] = table; |
357 int hash = key.hashCode(); |
358 int hash = key.hashCode(); |
358 int index = (hash & 0x7FFFFFFF) % tab.length; |
359 int index = (hash & 0x7FFFFFFF) % tab.length; |
359 for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) { |
360 for (Entry<?,?> e = tab[index] ; e != null ; e = e.next) { |
360 if ((e.hash == hash) && e.key.equals(key)) { |
361 if ((e.hash == hash) && e.key.equals(key)) { |
361 return e.value; |
362 return (V)e.value; |
362 } |
363 } |
363 } |
364 } |
364 return null; |
365 return null; |
365 } |
366 } |
366 |
367 |
377 * hashtable, in order to accommodate and access its entries more |
378 * hashtable, in order to accommodate and access its entries more |
378 * efficiently. This method is called automatically when the |
379 * efficiently. This method is called automatically when the |
379 * number of keys in the hashtable exceeds this hashtable's capacity |
380 * number of keys in the hashtable exceeds this hashtable's capacity |
380 * and load factor. |
381 * and load factor. |
381 */ |
382 */ |
|
383 @SuppressWarnings("unchecked") |
382 protected void rehash() { |
384 protected void rehash() { |
383 int oldCapacity = table.length; |
385 int oldCapacity = table.length; |
384 Entry[] oldMap = table; |
386 Entry<?,?>[] oldMap = table; |
385 |
387 |
386 // overflow-conscious code |
388 // overflow-conscious code |
387 int newCapacity = (oldCapacity << 1) + 1; |
389 int newCapacity = (oldCapacity << 1) + 1; |
388 if (newCapacity - MAX_ARRAY_SIZE > 0) { |
390 if (newCapacity - MAX_ARRAY_SIZE > 0) { |
389 if (oldCapacity == MAX_ARRAY_SIZE) |
391 if (oldCapacity == MAX_ARRAY_SIZE) |
390 // Keep running with MAX_ARRAY_SIZE buckets |
392 // Keep running with MAX_ARRAY_SIZE buckets |
391 return; |
393 return; |
392 newCapacity = MAX_ARRAY_SIZE; |
394 newCapacity = MAX_ARRAY_SIZE; |
393 } |
395 } |
394 Entry[] newMap = new Entry[newCapacity]; |
396 Entry<?,?>[] newMap = new Entry<?,?>[newCapacity]; |
395 |
397 |
396 modCount++; |
398 modCount++; |
397 threshold = (int)(newCapacity * loadFactor); |
399 threshold = (int)(newCapacity * loadFactor); |
398 table = newMap; |
400 table = newMap; |
399 |
401 |
400 for (int i = oldCapacity ; i-- > 0 ;) { |
402 for (int i = oldCapacity ; i-- > 0 ;) { |
401 for (Entry<K,V> old = oldMap[i] ; old != null ; ) { |
403 for (Entry<K,V> old = (Entry<K,V>)oldMap[i] ; old != null ; ) { |
402 Entry<K,V> e = old; |
404 Entry<K,V> e = old; |
403 old = old.next; |
405 old = old.next; |
404 |
406 |
405 int index = (e.hash & 0x7FFFFFFF) % newCapacity; |
407 int index = (e.hash & 0x7FFFFFFF) % newCapacity; |
406 e.next = newMap[index]; |
408 e.next = (Entry<K,V>)newMap[index]; |
407 newMap[index] = e; |
409 newMap[index] = e; |
408 } |
410 } |
409 } |
411 } |
410 } |
412 } |
411 |
413 |
431 if (value == null) { |
433 if (value == null) { |
432 throw new NullPointerException(); |
434 throw new NullPointerException(); |
433 } |
435 } |
434 |
436 |
435 // Makes sure the key is not already in the hashtable. |
437 // Makes sure the key is not already in the hashtable. |
436 Entry tab[] = table; |
438 Entry<?,?> tab[] = table; |
437 int hash = key.hashCode(); |
439 int hash = key.hashCode(); |
438 int index = (hash & 0x7FFFFFFF) % tab.length; |
440 int index = (hash & 0x7FFFFFFF) % tab.length; |
439 for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) { |
441 @SuppressWarnings("unchecked") |
440 if ((e.hash == hash) && e.key.equals(key)) { |
442 Entry<K,V> entry = (Entry<K,V>)tab[index]; |
441 V old = e.value; |
443 for(; entry != null ; entry = entry.next) { |
442 e.value = value; |
444 if ((entry.hash == hash) && entry.key.equals(key)) { |
|
445 V old = entry.value; |
|
446 entry.value = value; |
443 return old; |
447 return old; |
444 } |
448 } |
445 } |
449 } |
446 |
450 |
447 modCount++; |
451 modCount++; |
452 tab = table; |
456 tab = table; |
453 index = (hash & 0x7FFFFFFF) % tab.length; |
457 index = (hash & 0x7FFFFFFF) % tab.length; |
454 } |
458 } |
455 |
459 |
456 // Creates the new entry. |
460 // Creates the new entry. |
457 Entry<K,V> e = tab[index]; |
461 @SuppressWarnings("unchecked") |
|
462 Entry<K,V> e = (Entry<K,V>)tab[index]; |
458 tab[index] = new Entry<>(hash, key, value, e); |
463 tab[index] = new Entry<>(hash, key, value, e); |
459 count++; |
464 count++; |
460 return null; |
465 return null; |
461 } |
466 } |
462 |
467 |
468 * @return the value to which the key had been mapped in this hashtable, |
473 * @return the value to which the key had been mapped in this hashtable, |
469 * or <code>null</code> if the key did not have a mapping |
474 * or <code>null</code> if the key did not have a mapping |
470 * @throws NullPointerException if the key is <code>null</code> |
475 * @throws NullPointerException if the key is <code>null</code> |
471 */ |
476 */ |
472 public synchronized V remove(Object key) { |
477 public synchronized V remove(Object key) { |
473 Entry tab[] = table; |
478 Entry<?,?> tab[] = table; |
474 int hash = key.hashCode(); |
479 int hash = key.hashCode(); |
475 int index = (hash & 0x7FFFFFFF) % tab.length; |
480 int index = (hash & 0x7FFFFFFF) % tab.length; |
476 for (Entry<K,V> e = tab[index], prev = null ; e != null ; prev = e, e = e.next) { |
481 @SuppressWarnings("unchecked") |
|
482 Entry<K,V> e = (Entry<K,V>)tab[index]; |
|
483 for(Entry<K,V> prev = null ; e != null ; prev = e, e = e.next) { |
477 if ((e.hash == hash) && e.key.equals(key)) { |
484 if ((e.hash == hash) && e.key.equals(key)) { |
478 modCount++; |
485 modCount++; |
479 if (prev != null) { |
486 if (prev != null) { |
480 prev.next = e.next; |
487 prev.next = e.next; |
481 } else { |
488 } else { |
522 * |
529 * |
523 * @return a clone of the hashtable |
530 * @return a clone of the hashtable |
524 */ |
531 */ |
525 public synchronized Object clone() { |
532 public synchronized Object clone() { |
526 try { |
533 try { |
527 Hashtable<K,V> t = (Hashtable<K,V>) super.clone(); |
534 Hashtable<?,?> t = (Hashtable<?,?>)super.clone(); |
528 t.table = new Entry[table.length]; |
535 t.table = new Entry<?,?>[table.length]; |
529 for (int i = table.length ; i-- > 0 ; ) { |
536 for (int i = table.length ; i-- > 0 ; ) { |
530 t.table[i] = (table[i] != null) |
537 t.table[i] = (table[i] != null) |
531 ? (Entry<K,V>) table[i].clone() : null; |
538 ? (Entry<?,?>) table[i].clone() : null; |
532 } |
539 } |
533 t.keySet = null; |
540 t.keySet = null; |
534 t.entrySet = null; |
541 t.entrySet = null; |
535 t.values = null; |
542 t.values = null; |
536 t.modCount = 0; |
543 t.modCount = 0; |
673 } |
680 } |
674 |
681 |
675 public boolean contains(Object o) { |
682 public boolean contains(Object o) { |
676 if (!(o instanceof Map.Entry)) |
683 if (!(o instanceof Map.Entry)) |
677 return false; |
684 return false; |
678 Map.Entry entry = (Map.Entry)o; |
685 Map.Entry<?,?> entry = (Map.Entry<?,?>)o; |
679 Object key = entry.getKey(); |
686 Object key = entry.getKey(); |
680 Entry[] tab = table; |
687 Entry<?,?>[] tab = table; |
681 int hash = key.hashCode(); |
688 int hash = key.hashCode(); |
682 int index = (hash & 0x7FFFFFFF) % tab.length; |
689 int index = (hash & 0x7FFFFFFF) % tab.length; |
683 |
690 |
684 for (Entry e = tab[index]; e != null; e = e.next) |
691 for (Entry<?,?> e = tab[index]; e != null; e = e.next) |
685 if (e.hash==hash && e.equals(entry)) |
692 if (e.hash==hash && e.equals(entry)) |
686 return true; |
693 return true; |
687 return false; |
694 return false; |
688 } |
695 } |
689 |
696 |
690 public boolean remove(Object o) { |
697 public boolean remove(Object o) { |
691 if (!(o instanceof Map.Entry)) |
698 if (!(o instanceof Map.Entry)) |
692 return false; |
699 return false; |
693 Map.Entry<K,V> entry = (Map.Entry<K,V>) o; |
700 Map.Entry<?,?> entry = (Map.Entry<?,?>) o; |
694 K key = entry.getKey(); |
701 Object key = entry.getKey(); |
695 Entry[] tab = table; |
702 Entry<?,?>[] tab = table; |
696 int hash = key.hashCode(); |
703 int hash = key.hashCode(); |
697 int index = (hash & 0x7FFFFFFF) % tab.length; |
704 int index = (hash & 0x7FFFFFFF) % tab.length; |
698 |
705 |
699 for (Entry<K,V> e = tab[index], prev = null; e != null; |
706 @SuppressWarnings("unchecked") |
700 prev = e, e = e.next) { |
707 Entry<K,V> e = (Entry<K,V>)tab[index]; |
|
708 for(Entry<K,V> prev = null; e != null; prev = e, e = e.next) { |
701 if (e.hash==hash && e.equals(entry)) { |
709 if (e.hash==hash && e.equals(entry)) { |
702 modCount++; |
710 modCount++; |
703 if (prev != null) |
711 if (prev != null) |
704 prev.next = e.next; |
712 prev.next = e.next; |
705 else |
713 else |
774 if (o == this) |
782 if (o == this) |
775 return true; |
783 return true; |
776 |
784 |
777 if (!(o instanceof Map)) |
785 if (!(o instanceof Map)) |
778 return false; |
786 return false; |
779 Map<K,V> t = (Map<K,V>) o; |
787 Map<?,?> t = (Map<?,?>) o; |
780 if (t.size() != size()) |
788 if (t.size() != size()) |
781 return false; |
789 return false; |
782 |
790 |
783 try { |
791 try { |
784 Iterator<Map.Entry<K,V>> i = entrySet().iterator(); |
792 Iterator<Map.Entry<K,V>> i = entrySet().iterator(); |
824 int h = 0; |
832 int h = 0; |
825 if (count == 0 || loadFactor < 0) |
833 if (count == 0 || loadFactor < 0) |
826 return h; // Returns zero |
834 return h; // Returns zero |
827 |
835 |
828 loadFactor = -loadFactor; // Mark hashCode computation in progress |
836 loadFactor = -loadFactor; // Mark hashCode computation in progress |
829 Entry[] tab = table; |
837 Entry<?,?>[] tab = table; |
830 for (int i = 0; i < tab.length; i++) |
838 for (int i = 0; i < tab.length; i++) |
831 for (Entry e = tab[i]; e != null; e = e.next) |
839 for (Entry<?,?> e = tab[i]; e != null; e = e.next) |
832 h += e.key.hashCode() ^ e.value.hashCode(); |
840 h += e.key.hashCode() ^ e.value.hashCode(); |
833 loadFactor = -loadFactor; // Mark hashCode computation complete |
841 loadFactor = -loadFactor; // Mark hashCode computation complete |
834 |
842 |
835 return h; |
843 return h; |
836 } |
844 } |
857 s.writeInt(table.length); |
865 s.writeInt(table.length); |
858 s.writeInt(count); |
866 s.writeInt(count); |
859 |
867 |
860 // Stack copies of the entries in the table |
868 // Stack copies of the entries in the table |
861 for (int index = 0; index < table.length; index++) { |
869 for (int index = 0; index < table.length; index++) { |
862 Entry entry = table[index]; |
870 Entry<?,?> entry = table[index]; |
863 |
871 |
864 while (entry != null) { |
872 while (entry != null) { |
865 entryStack = |
873 entryStack = |
866 new Entry<>(0, entry.key, entry.value, entryStack); |
874 new Entry<>(0, entry.key, entry.value, entryStack); |
867 entry = entry.next; |
875 entry = entry.next; |
897 int length = (int)(elements * loadFactor) + (elements / 20) + 3; |
905 int length = (int)(elements * loadFactor) + (elements / 20) + 3; |
898 if (length > elements && (length & 1) == 0) |
906 if (length > elements && (length & 1) == 0) |
899 length--; |
907 length--; |
900 if (origlength > 0 && length > origlength) |
908 if (origlength > 0 && length > origlength) |
901 length = origlength; |
909 length = origlength; |
902 |
910 Entry<?,?>[] table = new Entry<?,?>[length]; |
903 Entry[] table = new Entry[length]; |
|
904 count = 0; |
911 count = 0; |
905 |
912 |
906 // Read the number of elements and then all the key/value objects |
913 // Read the number of elements and then all the key/value objects |
907 for (; elements > 0; elements--) { |
914 for (; elements > 0; elements--) { |
908 K key = (K)s.readObject(); |
915 @SuppressWarnings("unchecked") |
909 V value = (V)s.readObject(); |
916 K key = (K)s.readObject(); |
|
917 @SuppressWarnings("unchecked") |
|
918 V value = (V)s.readObject(); |
910 // synch could be eliminated for performance |
919 // synch could be eliminated for performance |
911 reconstitutionPut(table, key, value); |
920 reconstitutionPut(table, key, value); |
912 } |
921 } |
913 this.table = table; |
922 this.table = table; |
914 } |
923 } |
922 * checking for rehashing is necessary since the number of elements |
931 * checking for rehashing is necessary since the number of elements |
923 * initially in the table is known. The modCount is not incremented |
932 * initially in the table is known. The modCount is not incremented |
924 * because we are creating a new instance. Also, no return value |
933 * because we are creating a new instance. Also, no return value |
925 * is needed. |
934 * is needed. |
926 */ |
935 */ |
927 private void reconstitutionPut(Entry[] tab, K key, V value) |
936 private void reconstitutionPut(Entry<?,?>[] tab, K key, V value) |
928 throws StreamCorruptedException |
937 throws StreamCorruptedException |
929 { |
938 { |
930 if (value == null) { |
939 if (value == null) { |
931 throw new java.io.StreamCorruptedException(); |
940 throw new java.io.StreamCorruptedException(); |
932 } |
941 } |
933 // Makes sure the key is not already in the hashtable. |
942 // Makes sure the key is not already in the hashtable. |
934 // This should not happen in deserialized version. |
943 // This should not happen in deserialized version. |
935 int hash = key.hashCode(); |
944 int hash = key.hashCode(); |
936 int index = (hash & 0x7FFFFFFF) % tab.length; |
945 int index = (hash & 0x7FFFFFFF) % tab.length; |
937 for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) { |
946 for (Entry<?,?> e = tab[index] ; e != null ; e = e.next) { |
938 if ((e.hash == hash) && e.key.equals(key)) { |
947 if ((e.hash == hash) && e.key.equals(key)) { |
939 throw new java.io.StreamCorruptedException(); |
948 throw new java.io.StreamCorruptedException(); |
940 } |
949 } |
941 } |
950 } |
942 // Creates the new entry. |
951 // Creates the new entry. |
943 Entry<K,V> e = tab[index]; |
952 @SuppressWarnings("unchecked") |
|
953 Entry<K,V> e = (Entry<K,V>)tab[index]; |
944 tab[index] = new Entry<>(hash, key, value, e); |
954 tab[index] = new Entry<>(hash, key, value, e); |
945 count++; |
955 count++; |
946 } |
956 } |
947 |
957 |
948 /** |
958 /** |
959 this.key = key; |
969 this.key = key; |
960 this.value = value; |
970 this.value = value; |
961 this.next = next; |
971 this.next = next; |
962 } |
972 } |
963 |
973 |
|
974 @SuppressWarnings("unchecked") |
964 protected Object clone() { |
975 protected Object clone() { |
965 return new Entry<>(hash, key, value, |
976 return new Entry<>(hash, key, value, |
966 (next==null ? null : (Entry<K,V>) next.clone())); |
977 (next==null ? null : (Entry<K,V>) next.clone())); |
967 } |
978 } |
968 |
979 |
986 } |
997 } |
987 |
998 |
988 public boolean equals(Object o) { |
999 public boolean equals(Object o) { |
989 if (!(o instanceof Map.Entry)) |
1000 if (!(o instanceof Map.Entry)) |
990 return false; |
1001 return false; |
991 Map.Entry e = (Map.Entry)o; |
1002 Map.Entry<?,?> e = (Map.Entry<?,?>)o; |
992 |
1003 |
993 return (key==null ? e.getKey()==null : key.equals(e.getKey())) && |
1004 return (key==null ? e.getKey()==null : key.equals(e.getKey())) && |
994 (value==null ? e.getValue()==null : value.equals(e.getValue())); |
1005 (value==null ? e.getValue()==null : value.equals(e.getValue())); |
995 } |
1006 } |
996 |
1007 |
1014 * can be created with the Iterator methods disabled. This is necessary |
1025 * can be created with the Iterator methods disabled. This is necessary |
1015 * to avoid unintentionally increasing the capabilities granted a user |
1026 * to avoid unintentionally increasing the capabilities granted a user |
1016 * by passing an Enumeration. |
1027 * by passing an Enumeration. |
1017 */ |
1028 */ |
1018 private class Enumerator<T> implements Enumeration<T>, Iterator<T> { |
1029 private class Enumerator<T> implements Enumeration<T>, Iterator<T> { |
1019 Entry[] table = Hashtable.this.table; |
1030 Entry<?,?>[] table = Hashtable.this.table; |
1020 int index = table.length; |
1031 int index = table.length; |
1021 Entry<K,V> entry = null; |
1032 Entry<?,?> entry = null; |
1022 Entry<K,V> lastReturned = null; |
1033 Entry<?,?> lastReturned = null; |
1023 int type; |
1034 int type; |
1024 |
1035 |
1025 /** |
1036 /** |
1026 * Indicates whether this Enumerator is serving as an Iterator |
1037 * Indicates whether this Enumerator is serving as an Iterator |
1027 * or an Enumeration. (true -> Iterator). |
1038 * or an Enumeration. (true -> Iterator). |
1039 this.type = type; |
1050 this.type = type; |
1040 this.iterator = iterator; |
1051 this.iterator = iterator; |
1041 } |
1052 } |
1042 |
1053 |
1043 public boolean hasMoreElements() { |
1054 public boolean hasMoreElements() { |
1044 Entry<K,V> e = entry; |
1055 Entry<?,?> e = entry; |
1045 int i = index; |
1056 int i = index; |
1046 Entry[] t = table; |
1057 Entry<?,?>[] t = table; |
1047 /* Use locals for faster loop iteration */ |
1058 /* Use locals for faster loop iteration */ |
1048 while (e == null && i > 0) { |
1059 while (e == null && i > 0) { |
1049 e = t[--i]; |
1060 e = t[--i]; |
1050 } |
1061 } |
1051 entry = e; |
1062 entry = e; |
1052 index = i; |
1063 index = i; |
1053 return e != null; |
1064 return e != null; |
1054 } |
1065 } |
1055 |
1066 |
|
1067 @SuppressWarnings("unchecked") |
1056 public T nextElement() { |
1068 public T nextElement() { |
1057 Entry<K,V> et = entry; |
1069 Entry<?,?> et = entry; |
1058 int i = index; |
1070 int i = index; |
1059 Entry[] t = table; |
1071 Entry<?,?>[] t = table; |
1060 /* Use locals for faster loop iteration */ |
1072 /* Use locals for faster loop iteration */ |
1061 while (et == null && i > 0) { |
1073 while (et == null && i > 0) { |
1062 et = t[--i]; |
1074 et = t[--i]; |
1063 } |
1075 } |
1064 entry = et; |
1076 entry = et; |
1065 index = i; |
1077 index = i; |
1066 if (et != null) { |
1078 if (et != null) { |
1067 Entry<K,V> e = lastReturned = entry; |
1079 Entry<?,?> e = lastReturned = entry; |
1068 entry = e.next; |
1080 entry = e.next; |
1069 return type == KEYS ? (T)e.key : (type == VALUES ? (T)e.value : (T)e); |
1081 return type == KEYS ? (T)e.key : (type == VALUES ? (T)e.value : (T)e); |
1070 } |
1082 } |
1071 throw new NoSuchElementException("Hashtable Enumerator"); |
1083 throw new NoSuchElementException("Hashtable Enumerator"); |
1072 } |
1084 } |
1089 throw new IllegalStateException("Hashtable Enumerator"); |
1101 throw new IllegalStateException("Hashtable Enumerator"); |
1090 if (modCount != expectedModCount) |
1102 if (modCount != expectedModCount) |
1091 throw new ConcurrentModificationException(); |
1103 throw new ConcurrentModificationException(); |
1092 |
1104 |
1093 synchronized(Hashtable.this) { |
1105 synchronized(Hashtable.this) { |
1094 Entry[] tab = Hashtable.this.table; |
1106 Entry<?,?>[] tab = Hashtable.this.table; |
1095 int index = (lastReturned.hash & 0x7FFFFFFF) % tab.length; |
1107 int index = (lastReturned.hash & 0x7FFFFFFF) % tab.length; |
1096 |
1108 |
1097 for (Entry<K,V> e = tab[index], prev = null; e != null; |
1109 @SuppressWarnings("unchecked") |
1098 prev = e, e = e.next) { |
1110 Entry<K,V> e = (Entry<K,V>)tab[index]; |
|
1111 for(Entry<K,V> prev = null; e != null; prev = e, e = e.next) { |
1099 if (e == lastReturned) { |
1112 if (e == lastReturned) { |
1100 modCount++; |
1113 modCount++; |
1101 expectedModCount++; |
1114 expectedModCount++; |
1102 if (prev == null) |
1115 if (prev == null) |
1103 tab[index] = e.next; |
1116 tab[index] = e.next; |