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