1   /*
2    * %W% %E%
3    *
4    * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
5    * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6    */
7   
8   package java.util;
9   import java.io.*;
10  
11  /**
12   * This class implements a hashtable, which maps keys to values. Any
13   * non-<code>null</code> object can be used as a key or as a value. <p>
14   *
15   * To successfully store and retrieve objects from a hashtable, the
16   * objects used as keys must implement the <code>hashCode</code>
17   * method and the <code>equals</code> method. <p>
18   *
19   * An instance of <code>Hashtable</code> has two parameters that affect its
20   * performance: <i>initial capacity</i> and <i>load factor</i>.  The
21   * <i>capacity</i> is the number of <i>buckets</i> in the hash table, and the
22   * <i>initial capacity</i> is simply the capacity at the time the hash table
23   * is created.  Note that the hash table is <i>open</i>: in the case of a "hash
24   * collision", a single bucket stores multiple entries, which must be searched
25   * sequentially.  The <i>load factor</i> is a measure of how full the hash
26   * table is allowed to get before its capacity is automatically increased.
27   * The initial capacity and load factor parameters are merely hints to
28   * the implementation.  The exact details as to when and whether the rehash
29   * method is invoked are implementation-dependent.<p>
30   *
31   * Generally, the default load factor (.75) offers a good tradeoff between
32   * time and space costs.  Higher values decrease the space overhead but
33   * increase the time cost to look up an entry (which is reflected in most
34   * <tt>Hashtable</tt> operations, including <tt>get</tt> and <tt>put</tt>).<p>
35   *
36   * The initial capacity controls a tradeoff between wasted space and the
37   * need for <code>rehash</code> operations, which are time-consuming.
38   * No <code>rehash</code> operations will <i>ever</i> occur if the initial
39   * capacity is greater than the maximum number of entries the
40   * <tt>Hashtable</tt> will contain divided by its load factor.  However,
41   * setting the initial capacity too high can waste space.<p>
42   *
43   * If many entries are to be made into a <code>Hashtable</code>,
44   * creating it with a sufficiently large capacity may allow the
45   * entries to be inserted more efficiently than letting it perform
46   * automatic rehashing as needed to grow the table. <p>
47   *
48   * This example creates a hashtable of numbers. It uses the names of
49   * the numbers as keys:
50   * <pre>   {@code
51   *   Hashtable<String, Integer> numbers
52   *     = new Hashtable<String, Integer>();
53   *   numbers.put("one", 1);
54   *   numbers.put("two", 2);
55   *   numbers.put("three", 3);}</pre>
56   *
57   * <p>To retrieve a number, use the following code:
58   * <pre>   {@code
59   *   Integer n = numbers.get("two");
60   *   if (n != null) {
61   *     System.out.println("two = " + n);
62   *   }}</pre>
63   *
64   * <p>The iterators returned by the <tt>iterator</tt> method of the collections
65   * returned by all of this class's "collection view methods" are
66   * <em>fail-fast</em>: if the Hashtable is structurally modified at any time
67   * after the iterator is created, in any way except through the iterator's own
68   * <tt>remove</tt> method, the iterator will throw a {@link
69   * ConcurrentModificationException}.  Thus, in the face of concurrent
70   * modification, the iterator fails quickly and cleanly, rather than risking
71   * arbitrary, non-deterministic behavior at an undetermined time in the future.
72   * The Enumerations returned by Hashtable's keys and elements methods are
73   * <em>not</em> fail-fast.
74   *
75   * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
76   * as it is, generally speaking, impossible to make any hard guarantees in the
77   * presence of unsynchronized concurrent modification.  Fail-fast iterators
78   * throw <tt>ConcurrentModificationException</tt> on a best-effort basis.
79   * Therefore, it would be wrong to write a program that depended on this
80   * exception for its correctness: <i>the fail-fast behavior of iterators
81   * should be used only to detect bugs.</i>
82   *
83   * <p>As of the Java 2 platform v1.2, this class was retrofitted to
84   * implement the {@link Map} interface, making it a member of the
85   * <a href="{@docRoot}/../technotes/guides/collections/index.html"> Java
86   * Collections Framework</a>.  Unlike the new collection
87   * implementations, {@code Hashtable} is synchronized.
88   *
89   * @author  Arthur van Hoff
90   * @author  Josh Bloch
91   * @author  Neal Gafter
92   * @version %I%, %G%
93   * @see     Object#equals(java.lang.Object)
94   * @see     Object#hashCode()
95   * @see     Hashtable#rehash()
96   * @see     Collection
97   * @see     Map
98   * @see     HashMap
99   * @see     TreeMap
100  * @since JDK1.0
101  */
102 public class Hashtable<K,V>
103     extends Dictionary<K,V>
104     implements Map<K,V>, Cloneable, java.io.Serializable {
105 
106     /**
107      * The hash table data.
108      */
109     private transient Entry[] table;
110 
111     /**
112      * The total number of entries in the hash table.
113      */
114     private transient int count;
115 
116     /**
117      * The table is rehashed when its size exceeds this threshold.  (The
118      * value of this field is (int)(capacity * loadFactor).)
119      *
120      * @serial
121      */
122     private int threshold;
123 
124     /**
125      * The load factor for the hashtable.
126      *
127      * @serial
128      */
129     private float loadFactor;
130 
131     /**
132      * The number of times this Hashtable has been structurally modified
133      * Structural modifications are those that change the number of entries in
134      * the Hashtable or otherwise modify its internal structure (e.g.,
135      * rehash).  This field is used to make iterators on Collection-views of
136      * the Hashtable fail-fast.  (See ConcurrentModificationException).
137      */
138     private transient int modCount = 0;
139 
140     /** use serialVersionUID from JDK 1.0.2 for interoperability */
141     private static final long serialVersionUID = 1421746759512286392L;
142 
143     /**
144      * Constructs a new, empty hashtable with the specified initial
145      * capacity and the specified load factor.
146      *
147      * @param      initialCapacity   the initial capacity of the hashtable.
148      * @param      loadFactor        the load factor of the hashtable.
149      * @exception  IllegalArgumentException  if the initial capacity is less
150      *             than zero, or if the load factor is nonpositive.
151      */
152     public Hashtable(int initialCapacity, float loadFactor) {
153     if (initialCapacity < 0)
154         throw new IllegalArgumentException("Illegal Capacity: "+
155                                                initialCapacity);
156         if (loadFactor <= 0 || Float.isNaN(loadFactor))
157             throw new IllegalArgumentException("Illegal Load: "+loadFactor);
158 
159         if (initialCapacity==0)
160             initialCapacity = 1;
161     this.loadFactor = loadFactor;
162     table = new Entry[initialCapacity];
163     threshold = (int)(initialCapacity * loadFactor);
164     }
165 
166     /**
167      * Constructs a new, empty hashtable with the specified initial capacity
168      * and default load factor (0.75).
169      *
170      * @param     initialCapacity   the initial capacity of the hashtable.
171      * @exception IllegalArgumentException if the initial capacity is less
172      *              than zero.
173      */
174     public Hashtable(int initialCapacity) {
175     this(initialCapacity, 0.75f);
176     }
177 
178     /**
179      * Constructs a new, empty hashtable with a default initial capacity (11)
180      * and load factor (0.75).
181      */
182     public Hashtable() {
183     this(11, 0.75f);
184     }
185 
186     /**
187      * Constructs a new hashtable with the same mappings as the given
188      * Map.  The hashtable is created with an initial capacity sufficient to
189      * hold the mappings in the given Map and a default load factor (0.75).
190      *
191      * @param t the map whose mappings are to be placed in this map.
192      * @throws NullPointerException if the specified map is null.
193      * @since   1.2
194      */
195     public Hashtable(Map<? extends K, ? extends V> t) {
196     this(Math.max(2*t.size(), 11), 0.75f);
197     putAll(t);
198     }
199 
200     /**
201      * Returns the number of keys in this hashtable.
202      *
203      * @return  the number of keys in this hashtable.
204      */
205     public synchronized int size() {
206     return count;
207     }
208 
209     /**
210      * Tests if this hashtable maps no keys to values.
211      *
212      * @return  <code>true</code> if this hashtable maps no keys to values;
213      *          <code>false</code> otherwise.
214      */
215     public synchronized boolean isEmpty() {
216     return count == 0;
217     }
218 
219     /**
220      * Returns an enumeration of the keys in this hashtable.
221      *
222      * @return  an enumeration of the keys in this hashtable.
223      * @see     Enumeration
224      * @see     #elements()
225      * @see #keySet()
226      * @see Map
227      */
228     public synchronized Enumeration<K> keys() {
229     return this.<K>getEnumeration(KEYS);
230     }
231 
232     /**
233      * Returns an enumeration of the values in this hashtable.
234      * Use the Enumeration methods on the returned object to fetch the elements
235      * sequentially.
236      *
237      * @return  an enumeration of the values in this hashtable.
238      * @see     java.util.Enumeration
239      * @see     #keys()
240      * @see #values()
241      * @see Map
242      */
243     public synchronized Enumeration<V> elements() {
244     return this.<V>getEnumeration(VALUES);
245     }
246 
247     /**
248      * Tests if some key maps into the specified value in this hashtable.
249      * This operation is more expensive than the {@link #containsKey
250      * containsKey} method.
251      *
252      * <p>Note that this method is identical in functionality to
253      * {@link #containsValue containsValue}, (which is part of the
254      * {@link Map} interface in the collections framework).
255      *
256      * @param      value   a value to search for
257      * @return     <code>true</code> if and only if some key maps to the
258      *             <code>value</code> argument in this hashtable as
259      *             determined by the <tt>equals</tt> method;
260      *             <code>false</code> otherwise.
261      * @exception  NullPointerException  if the value is <code>null</code>
262      */
263     public synchronized boolean contains(Object value) {
264     if (value == null) {
265         throw new NullPointerException();
266     }
267 
268     Entry tab[] = table;
269     for (int i = tab.length ; i-- > 0 ;) {
270         for (Entry<K,V> e = tab[i] ; e != null ; e = e.next) {
271         if (e.value.equals(value)) {
272             return true;
273         }
274         }
275     }
276     return false;
277     }
278 
279     /**
280      * Returns true if this hashtable maps one or more keys to this value.
281      *
282      * <p>Note that this method is identical in functionality to {@link
283      * #contains contains} (which predates the {@link Map} interface).
284      *
285      * @param value value whose presence in this hashtable is to be tested
286      * @return <tt>true</tt> if this map maps one or more keys to the
287      *         specified value
288      * @throws NullPointerException  if the value is <code>null</code>
289      * @since 1.2
290      */
291     public boolean containsValue(Object value) {
292     return contains(value);
293     }
294 
295     /**
296      * Tests if the specified object is a key in this hashtable.
297      *
298      * @param   key   possible key
299      * @return  <code>true</code> if and only if the specified object
300      *          is a key in this hashtable, as determined by the
301      *          <tt>equals</tt> method; <code>false</code> otherwise.
302      * @throws  NullPointerException  if the key is <code>null</code>
303      * @see     #contains(Object)
304      */
305     public synchronized boolean containsKey(Object key) {
306     Entry tab[] = table;
307     int hash = key.hashCode();
308     int index = (hash & 0x7FFFFFFF) % tab.length;
309     for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {
310         if ((e.hash == hash) && e.key.equals(key)) {
311         return true;
312         }
313     }
314     return false;
315     }
316 
317     /**
318      * Returns the value to which the specified key is mapped,
319      * or {@code null} if this map contains no mapping for the key.
320      *
321      * <p>More formally, if this map contains a mapping from a key
322      * {@code k} to a value {@code v} such that {@code (key.equals(k))},
323      * then this method returns {@code v}; otherwise it returns
324      * {@code null}.  (There can be at most one such mapping.)
325      *
326      * @param key the key whose associated value is to be returned
327      * @return the value to which the specified key is mapped, or
328      *         {@code null} if this map contains no mapping for the key
329      * @throws NullPointerException if the specified key is null
330      * @see     #put(Object, Object)
331      */
332     public synchronized V get(Object key) {
333     Entry tab[] = table;
334     int hash = key.hashCode();
335     int index = (hash & 0x7FFFFFFF) % tab.length;
336     for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {
337         if ((e.hash == hash) && e.key.equals(key)) {
338         return e.value;
339         }
340     }
341     return null;
342     }
343 
344     /**
345      * Increases the capacity of and internally reorganizes this
346      * hashtable, in order to accommodate and access its entries more
347      * efficiently.  This method is called automatically when the
348      * number of keys in the hashtable exceeds this hashtable's capacity
349      * and load factor.
350      */
351     protected void rehash() {
352     int oldCapacity = table.length;
353     Entry[] oldMap = table;
354 
355     int newCapacity = oldCapacity * 2 + 1;
356     Entry[] newMap = new Entry[newCapacity];
357 
358     modCount++;
359     threshold = (int)(newCapacity * loadFactor);
360     table = newMap;
361 
362     for (int i = oldCapacity ; i-- > 0 ;) {
363         for (Entry<K,V> old = oldMap[i] ; old != null ; ) {
364         Entry<K,V> e = old;
365         old = old.next;
366 
367         int index = (e.hash & 0x7FFFFFFF) % newCapacity;
368         e.next = newMap[index];
369         newMap[index] = e;
370         }
371     }
372     }
373 
374     /**
375      * Maps the specified <code>key</code> to the specified
376      * <code>value</code> in this hashtable. Neither the key nor the
377      * value can be <code>null</code>. <p>
378      *
379      * The value can be retrieved by calling the <code>get</code> method
380      * with a key that is equal to the original key.
381      *
382      * @param      key     the hashtable key
383      * @param      value   the value
384      * @return     the previous value of the specified key in this hashtable,
385      *             or <code>null</code> if it did not have one
386      * @exception  NullPointerException  if the key or value is
387      *               <code>null</code>
388      * @see     Object#equals(Object)
389      * @see     #get(Object)
390      */
391     public synchronized V put(K key, V value) {
392     // Make sure the value is not null
393     if (value == null) {
394         throw new NullPointerException();
395     }
396 
397     // Makes sure the key is not already in the hashtable.
398     Entry tab[] = table;
399     int hash = key.hashCode();
400     int index = (hash & 0x7FFFFFFF) % tab.length;
401     for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {
402         if ((e.hash == hash) && e.key.equals(key)) {
403         V old = e.value;
404         e.value = value;
405         return old;
406         }
407     }
408 
409     modCount++;
410     if (count >= threshold) {
411         // Rehash the table if the threshold is exceeded
412         rehash();
413 
414             tab = table;
415             index = (hash & 0x7FFFFFFF) % tab.length;
416     }
417 
418     // Creates the new entry.
419     Entry<K,V> e = tab[index];
420     tab[index] = new Entry<K,V>(hash, key, value, e);
421     count++;
422     return null;
423     }
424 
425     /**
426      * Removes the key (and its corresponding value) from this
427      * hashtable. This method does nothing if the key is not in the hashtable.
428      *
429      * @param   key   the key that needs to be removed
430      * @return  the value to which the key had been mapped in this hashtable,
431      *          or <code>null</code> if the key did not have a mapping
432      * @throws  NullPointerException  if the key is <code>null</code>
433      */
434     public synchronized V remove(Object key) {
435     Entry tab[] = table;
436     int hash = key.hashCode();
437     int index = (hash & 0x7FFFFFFF) % tab.length;
438     for (Entry<K,V> e = tab[index], prev = null ; e != null ; prev = e, e = e.next) {
439         if ((e.hash == hash) && e.key.equals(key)) {
440         modCount++;
441         if (prev != null) {
442             prev.next = e.next;
443         } else {
444             tab[index] = e.next;
445         }
446         count--;
447         V oldValue = e.value;
448         e.value = null;
449         return oldValue;
450         }
451     }
452     return null;
453     }
454 
455     /**
456      * Copies all of the mappings from the specified map to this hashtable.
457      * These mappings will replace any mappings that this hashtable had for any
458      * of the keys currently in the specified map.
459      *
460      * @param t mappings to be stored in this map
461      * @throws NullPointerException if the specified map is null
462      * @since 1.2
463      */
464     public synchronized void putAll(Map<? extends K, ? extends V> t) {
465         for (Map.Entry<? extends K, ? extends V> e : t.entrySet())
466             put(e.getKey(), e.getValue());
467     }
468 
469     /**
470      * Clears this hashtable so that it contains no keys.
471      */
472     public synchronized void clear() {
473     Entry tab[] = table;
474     modCount++;
475     for (int index = tab.length; --index >= 0; )
476         tab[index] = null;
477     count = 0;
478     }
479 
480     /**
481      * Creates a shallow copy of this hashtable. All the structure of the
482      * hashtable itself is copied, but the keys and values are not cloned.
483      * This is a relatively expensive operation.
484      *
485      * @return  a clone of the hashtable
486      */
487     public synchronized Object clone() {
488     try {
489         Hashtable<K,V> t = (Hashtable<K,V>) super.clone();
490         t.table = new Entry[table.length];
491         for (int i = table.length ; i-- > 0 ; ) {
492         t.table[i] = (table[i] != null)
493             ? (Entry<K,V>) table[i].clone() : null;
494         }
495         t.keySet = null;
496         t.entrySet = null;
497             t.values = null;
498         t.modCount = 0;
499         return t;
500     } catch (CloneNotSupportedException e) {
501         // this shouldn't happen, since we are Cloneable
502         throw new InternalError();
503     }
504     }
505 
506     /**
507      * Returns a string representation of this <tt>Hashtable</tt> object
508      * in the form of a set of entries, enclosed in braces and separated
509      * by the ASCII characters "<tt>,&nbsp;</tt>" (comma and space). Each
510      * entry is rendered as the key, an equals sign <tt>=</tt>, and the
511      * associated element, where the <tt>toString</tt> method is used to
512      * convert the key and element to strings.
513      *
514      * @return  a string representation of this hashtable
515      */
516     public synchronized String toString() {
517     int max = size() - 1;
518     if (max == -1)
519         return "{}";
520 
521     StringBuilder sb = new StringBuilder();
522     Iterator<Map.Entry<K,V>> it = entrySet().iterator();
523 
524     sb.append('{');
525     for (int i = 0; ; i++) {
526         Map.Entry<K,V> e = it.next();
527             K key = e.getKey();
528             V value = e.getValue();
529             sb.append(key   == this ? "(this Map)" : key.toString());
530         sb.append('=');
531         sb.append(value == this ? "(this Map)" : value.toString());
532 
533         if (i == max)
534         return sb.append('}').toString();
535         sb.append(", ");
536     }
537     }
538 
539 
540     private <T> Enumeration<T> getEnumeration(int type) {
541     if (count == 0) {
542         return (Enumeration<T>)emptyEnumerator;
543     } else {
544         return new Enumerator<T>(type, false);
545     }
546     }
547 
548     private <T> Iterator<T> getIterator(int type) {
549     if (count == 0) {
550         return (Iterator<T>) emptyIterator;
551     } else {
552         return new Enumerator<T>(type, true);
553     }
554     }
555 
556     // Views
557 
558     /**
559      * Each of these fields are initialized to contain an instance of the
560      * appropriate view the first time this view is requested.  The views are
561      * stateless, so there's no reason to create more than one of each.
562      */
563     private transient volatile Set<K> keySet = null;
564     private transient volatile Set<Map.Entry<K,V>> entrySet = null;
565     private transient volatile Collection<V> values = null;
566 
567     /**
568      * Returns a {@link Set} view of the keys contained in this map.
569      * The set is backed by the map, so changes to the map are
570      * reflected in the set, and vice-versa.  If the map is modified
571      * while an iteration over the set is in progress (except through
572      * the iterator's own <tt>remove</tt> operation), the results of
573      * the iteration are undefined.  The set supports element removal,
574      * which removes the corresponding mapping from the map, via the
575      * <tt>Iterator.remove</tt>, <tt>Set.remove</tt>,
576      * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt>
577      * operations.  It does not support the <tt>add</tt> or <tt>addAll</tt>
578      * operations.
579      *
580      * @since 1.2
581      */
582     public Set<K> keySet() {
583     if (keySet == null)
584         keySet = Collections.synchronizedSet(new KeySet(), this);
585     return keySet;
586     }
587 
588     private class KeySet extends AbstractSet<K> {
589         public Iterator<K> iterator() {
590         return getIterator(KEYS);
591         }
592         public int size() {
593             return count;
594         }
595         public boolean contains(Object o) {
596             return containsKey(o);
597         }
598         public boolean remove(Object o) {
599             return Hashtable.this.remove(o) != null;
600         }
601         public void clear() {
602             Hashtable.this.clear();
603         }
604     }
605 
606     /**
607      * Returns a {@link Set} view of the mappings contained in this map.
608      * The set is backed by the map, so changes to the map are
609      * reflected in the set, and vice-versa.  If the map is modified
610      * while an iteration over the set is in progress (except through
611      * the iterator's own <tt>remove</tt> operation, or through the
612      * <tt>setValue</tt> operation on a map entry returned by the
613      * iterator) the results of the iteration are undefined.  The set
614      * supports element removal, which removes the corresponding
615      * mapping from the map, via the <tt>Iterator.remove</tt>,
616      * <tt>Set.remove</tt>, <tt>removeAll</tt>, <tt>retainAll</tt> and
617      * <tt>clear</tt> operations.  It does not support the
618      * <tt>add</tt> or <tt>addAll</tt> operations.
619      *
620      * @since 1.2
621      */
622     public Set<Map.Entry<K,V>> entrySet() {
623     if (entrySet==null)
624         entrySet = Collections.synchronizedSet(new EntrySet(), this);
625     return entrySet;
626     }
627 
628     private class EntrySet extends AbstractSet<Map.Entry<K,V>> {
629         public Iterator<Map.Entry<K,V>> iterator() {
630         return getIterator(ENTRIES);
631         }
632 
633     public boolean add(Map.Entry<K,V> o) {
634         return super.add(o);
635     }
636 
637         public boolean contains(Object o) {
638             if (!(o instanceof Map.Entry))
639                 return false;
640             Map.Entry entry = (Map.Entry)o;
641             Object key = entry.getKey();
642             Entry[] tab = table;
643             int hash = key.hashCode();
644             int index = (hash & 0x7FFFFFFF) % tab.length;
645 
646             for (Entry e = tab[index]; e != null; e = e.next)
647                 if (e.hash==hash && e.equals(entry))
648                     return true;
649             return false;
650         }
651 
652         public boolean remove(Object o) {
653             if (!(o instanceof Map.Entry))
654                 return false;
655             Map.Entry<K,V> entry = (Map.Entry<K,V>) o;
656         K key = entry.getKey();
657             Entry[] tab = table;
658             int hash = key.hashCode();
659             int index = (hash & 0x7FFFFFFF) % tab.length;
660 
661             for (Entry<K,V> e = tab[index], prev = null; e != null;
662                  prev = e, e = e.next) {
663                 if (e.hash==hash && e.equals(entry)) {
664                     modCount++;
665                     if (prev != null)
666                         prev.next = e.next;
667                     else
668                         tab[index] = e.next;
669 
670                     count--;
671                     e.value = null;
672                     return true;
673                 }
674             }
675             return false;
676         }
677 
678         public int size() {
679             return count;
680         }
681 
682         public void clear() {
683             Hashtable.this.clear();
684         }
685     }
686 
687     /**
688      * Returns a {@link Collection} view of the values contained in this map.
689      * The collection is backed by the map, so changes to the map are
690      * reflected in the collection, and vice-versa.  If the map is
691      * modified while an iteration over the collection is in progress
692      * (except through the iterator's own <tt>remove</tt> operation),
693      * the results of the iteration are undefined.  The collection
694      * supports element removal, which removes the corresponding
695      * mapping from the map, via the <tt>Iterator.remove</tt>,
696      * <tt>Collection.remove</tt>, <tt>removeAll</tt>,
697      * <tt>retainAll</tt> and <tt>clear</tt> operations.  It does not
698      * support the <tt>add</tt> or <tt>addAll</tt> operations.
699      *
700      * @since 1.2
701      */
702     public Collection<V> values() {
703     if (values==null)
704         values = Collections.synchronizedCollection(new ValueCollection(),
705                                                         this);
706         return values;
707     }
708 
709     private class ValueCollection extends AbstractCollection<V> {
710         public Iterator<V> iterator() {
711         return getIterator(VALUES);
712         }
713         public int size() {
714             return count;
715         }
716         public boolean contains(Object o) {
717             return containsValue(o);
718         }
719         public void clear() {
720             Hashtable.this.clear();
721         }
722     }
723 
724     // Comparison and hashing
725 
726     /**
727      * Compares the specified Object with this Map for equality,
728      * as per the definition in the Map interface.
729      *
730      * @param  o object to be compared for equality with this hashtable
731      * @return true if the specified Object is equal to this Map
732      * @see Map#equals(Object)
733      * @since 1.2
734      */
735     public synchronized boolean equals(Object o) {
736     if (o == this)
737         return true;
738 
739     if (!(o instanceof Map))
740         return false;
741     Map<K,V> t = (Map<K,V>) o;
742     if (t.size() != size())
743         return false;
744 
745         try {
746             Iterator<Map.Entry<K,V>> i = entrySet().iterator();
747             while (i.hasNext()) {
748                 Map.Entry<K,V> e = i.next();
749                 K key = e.getKey();
750                 V value = e.getValue();
751                 if (value == null) {
752                     if (!(t.get(key)==null && t.containsKey(key)))
753                         return false;
754                 } else {
755                     if (!value.equals(t.get(key)))
756                         return false;
757                 }
758             }
759         } catch (ClassCastException unused)   {
760             return false;
761         } catch (NullPointerException unused) {
762             return false;
763         }
764 
765     return true;
766     }
767 
768     /**
769      * Returns the hash code value for this Map as per the definition in the
770      * Map interface.
771      *
772      * @see Map#hashCode()
773      * @since 1.2
774      */
775     public synchronized int hashCode() {
776         /*
777          * This code detects the recursion caused by computing the hash code
778          * of a self-referential hash table and prevents the stack overflow
779          * that would otherwise result.  This allows certain 1.1-era
780          * applets with self-referential hash tables to work.  This code
781          * abuses the loadFactor field to do double-duty as a hashCode
782          * in progress flag, so as not to worsen the space performance.
783          * A negative load factor indicates that hash code computation is
784          * in progress.
785          */
786         int h = 0;
787         if (count == 0 || loadFactor < 0)
788             return h;  // Returns zero
789 
790         loadFactor = -loadFactor;  // Mark hashCode computation in progress
791         Entry[] tab = table;
792         for (int i = 0; i < tab.length; i++)
793             for (Entry e = tab[i]; e != null; e = e.next)
794                 h += e.key.hashCode() ^ e.value.hashCode();
795         loadFactor = -loadFactor;  // Mark hashCode computation complete
796 
797     return h;
798     }
799 
800     /**
801      * Save the state of the Hashtable to a stream (i.e., serialize it).
802      *
803      * @serialData The <i>capacity</i> of the Hashtable (the length of the
804      *         bucket array) is emitted (int), followed by the
805      *         <i>size</i> of the Hashtable (the number of key-value
806      *         mappings), followed by the key (Object) and value (Object)
807      *         for each key-value mapping represented by the Hashtable
808      *         The key-value mappings are emitted in no particular order.
809      */
810     private synchronized void writeObject(java.io.ObjectOutputStream s)
811         throws IOException
812     {
813     // Write out the length, threshold, loadfactor
814     s.defaultWriteObject();
815 
816     // Write out length, count of elements and then the key/value objects
817     s.writeInt(table.length);
818     s.writeInt(count);
819     for (int index = table.length-1; index >= 0; index--) {
820         Entry entry = table[index];
821 
822         while (entry != null) {
823         s.writeObject(entry.key);
824         s.writeObject(entry.value);
825         entry = entry.next;
826         }
827     }
828     }
829 
830     /**
831      * Reconstitute the Hashtable from a stream (i.e., deserialize it).
832      */
833     private void readObject(java.io.ObjectInputStream s)
834          throws IOException, ClassNotFoundException
835     {
836     // Read in the length, threshold, and loadfactor
837     s.defaultReadObject();
838 
839     // Read the original length of the array and number of elements
840     int origlength = s.readInt();
841     int elements = s.readInt();
842 
843     // Compute new size with a bit of room 5% to grow but
844     // no larger than the original size.  Make the length
845     // odd if it's large enough, this helps distribute the entries.
846     // Guard against the length ending up zero, that's not valid.
847     int length = (int)(elements * loadFactor) + (elements / 20) + 3;
848     if (length > elements && (length & 1) == 0)
849         length--;
850     if (origlength > 0 && length > origlength)
851         length = origlength;
852 
853     Entry[] table = new Entry[length];
854     count = 0;
855 
856     // Read the number of elements and then all the key/value objects
857     for (; elements > 0; elements--) {
858         K key = (K)s.readObject();
859         V value = (V)s.readObject();
860             // synch could be eliminated for performance
861             reconstitutionPut(table, key, value);
862     }
863     this.table = table;
864     }
865 
866     /**
867      * The put method used by readObject. This is provided because put
868      * is overridable and should not be called in readObject since the
869      * subclass will not yet be initialized.
870      *
871      * <p>This differs from the regular put method in several ways. No
872      * checking for rehashing is necessary since the number of elements
873      * initially in the table is known. The modCount is not incremented
874      * because we are creating a new instance. Also, no return value
875      * is needed.
876      */
877     private void reconstitutionPut(Entry[] tab, K key, V value)
878         throws StreamCorruptedException
879     {
880         if (value == null) {
881             throw new java.io.StreamCorruptedException();
882         }
883         // Makes sure the key is not already in the hashtable.
884         // This should not happen in deserialized version.
885         int hash = key.hashCode();
886         int index = (hash & 0x7FFFFFFF) % tab.length;
887         for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {
888             if ((e.hash == hash) && e.key.equals(key)) {
889                 throw new java.io.StreamCorruptedException();
890             }
891         }
892         // Creates the new entry.
893         Entry<K,V> e = tab[index];
894         tab[index] = new Entry<K,V>(hash, key, value, e);
895         count++;
896     }
897 
898     /**
899      * Hashtable collision list.
900      */
901     private static class Entry<K,V> implements Map.Entry<K,V> {
902     int hash;
903     K key;
904     V value;
905     Entry<K,V> next;
906 
907     protected Entry(int hash, K key, V value, Entry<K,V> next) {
908         this.hash = hash;
909         this.key = key;
910         this.value = value;
911         this.next = next;
912     }
913 
914     protected Object clone() {
915         return new Entry<K,V>(hash, key, value,
916                   (next==null ? null : (Entry<K,V>) next.clone()));
917     }
918 
919     // Map.Entry Ops
920 
921     public K getKey() {
922         return key;
923     }
924 
925     public V getValue() {
926         return value;
927     }
928 
929     public V setValue(V value) {
930         if (value == null)
931         throw new NullPointerException();
932 
933         V oldValue = this.value;
934         this.value = value;
935         return oldValue;
936     }
937 
938     public boolean equals(Object o) {
939         if (!(o instanceof Map.Entry))
940         return false;
941         Map.Entry e = (Map.Entry)o;
942 
943         return (key==null ? e.getKey()==null : key.equals(e.getKey())) &&
944            (value==null ? e.getValue()==null : value.equals(e.getValue()));
945     }
946 
947     public int hashCode() {
948         return hash ^ (value==null ? 0 : value.hashCode());
949     }
950 
951     public String toString() {
952         return key.toString()+"="+value.toString();
953     }
954     }
955 
956     // Types of Enumerations/Iterations
957     private static final int KEYS = 0;
958     private static final int VALUES = 1;
959     private static final int ENTRIES = 2;
960 
961     /**
962      * A hashtable enumerator class.  This class implements both the
963      * Enumeration and Iterator interfaces, but individual instances
964      * can be created with the Iterator methods disabled.  This is necessary
965      * to avoid unintentionally increasing the capabilities granted a user
966      * by passing an Enumeration.
967      */
968     private class Enumerator<T> implements Enumeration<T>, Iterator<T> {
969     Entry[] table = Hashtable.this.table;
970     int index = table.length;
971     Entry<K,V> entry = null;
972     Entry<K,V> lastReturned = null;
973     int type;
974 
975     /**
976      * Indicates whether this Enumerator is serving as an Iterator
977      * or an Enumeration.  (true -> Iterator).
978      */
979     boolean iterator;
980 
981     /**
982      * The modCount value that the iterator believes that the backing
983      * Hashtable should have.  If this expectation is violated, the iterator
984      * has detected concurrent modification.
985      */
986     protected int expectedModCount = modCount;
987 
988     Enumerator(int type, boolean iterator) {
989         this.type = type;
990         this.iterator = iterator;
991     }
992 
993     public boolean hasMoreElements() {
994         Entry<K,V> e = entry;
995         int i = index;
996         Entry[] t = table;
997         /* Use locals for faster loop iteration */
998         while (e == null && i > 0) {
999         e = t[--i];
1000        }
1001        entry = e;
1002        index = i;
1003        return e != null;
1004    }
1005
1006    public T nextElement() {
1007        Entry<K,V> et = entry;
1008        int i = index;
1009        Entry[] t = table;
1010        /* Use locals for faster loop iteration */
1011        while (et == null && i > 0) {
1012        et = t[--i];
1013        }
1014        entry = et;
1015        index = i;
1016        if (et != null) {
1017        Entry<K,V> e = lastReturned = entry;
1018        entry = e.next;
1019        return type == KEYS ? (T)e.key : (type == VALUES ? (T)e.value : (T)e);
1020        }
1021        throw new NoSuchElementException("Hashtable Enumerator");
1022    }
1023
1024    // Iterator methods
1025    public boolean hasNext() {
1026        return hasMoreElements();
1027    }
1028
1029    public T next() {
1030        if (modCount != expectedModCount)
1031        throw new ConcurrentModificationException();
1032        return nextElement();
1033    }
1034
1035    public void remove() {
1036        if (!iterator)
1037        throw new UnsupportedOperationException();
1038        if (lastReturned == null)
1039        throw new IllegalStateException("Hashtable Enumerator");
1040        if (modCount != expectedModCount)
1041        throw new ConcurrentModificationException();
1042
1043        synchronized(Hashtable.this) {
1044        Entry[] tab = Hashtable.this.table;
1045        int index = (lastReturned.hash & 0x7FFFFFFF) % tab.length;
1046
1047        for (Entry<K,V> e = tab[index], prev = null; e != null;
1048             prev = e, e = e.next) {
1049            if (e == lastReturned) {
1050            modCount++;
1051            expectedModCount++;
1052            if (prev == null)
1053                tab[index] = e.next;
1054            else
1055                prev.next = e.next;
1056            count--;
1057            lastReturned = null;
1058            return;
1059            }
1060        }
1061        throw new ConcurrentModificationException();
1062        }
1063    }
1064    }
1065
1066
1067    private static Enumeration emptyEnumerator = new EmptyEnumerator();
1068    private static Iterator emptyIterator = new EmptyIterator();
1069
1070    /**
1071     * A hashtable enumerator class for empty hash tables, specializes
1072     * the general Enumerator
1073     */
1074    private static class EmptyEnumerator implements Enumeration<Object> {
1075
1076    EmptyEnumerator() {
1077    }
1078
1079    public boolean hasMoreElements() {
1080        return false;
1081    }
1082
1083    public Object nextElement() {
1084        throw new NoSuchElementException("Hashtable Enumerator");
1085    }
1086    }
1087
1088
1089    /**
1090     * A hashtable iterator class for empty hash tables
1091     */
1092    private static class EmptyIterator implements Iterator<Object> {
1093
1094    EmptyIterator() {
1095    }
1096
1097    public boolean hasNext() {
1098        return false;
1099    }
1100
1101    public Object next() {
1102        throw new NoSuchElementException("Hashtable Iterator");
1103    }
1104
1105    public void remove() {
1106        throw new IllegalStateException("Hashtable Iterator");
1107    }
1108
1109    }
1110
1111}
1112