jdk/src/share/classes/java/util/Hashtable.java
changeset 12448 b95438b17098
parent 10419 12c063b39232
child 12859 c44b88bb9b5e
equal deleted inserted replaced
12447:92676a77a667 12448:b95438b17098
   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 {
   506 
   513 
   507     /**
   514     /**
   508      * Clears this hashtable so that it contains no keys.
   515      * Clears this hashtable so that it contains no keys.
   509      */
   516      */
   510     public synchronized void clear() {
   517     public synchronized void clear() {
   511         Entry tab[] = table;
   518         Entry<?,?> tab[] = table;
   512         modCount++;
   519         modCount++;
   513         for (int index = tab.length; --index >= 0; )
   520         for (int index = tab.length; --index >= 0; )
   514             tab[index] = null;
   521             tab[index] = null;
   515         count = 0;
   522         count = 0;
   516     }
   523     }
   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;