IdentityHashMap.java revision c3a9db83a352d92d5a6e0098f22bde07e34a1d3b
1/*
2 * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package java.util;
27
28import java.io.*;
29import java.util.function.BiConsumer;
30import java.util.function.Consumer;
31
32/**
33 * This class implements the <tt>Map</tt> interface with a hash table, using
34 * reference-equality in place of object-equality when comparing keys (and
35 * values).  In other words, in an <tt>IdentityHashMap</tt>, two keys
36 * <tt>k1</tt> and <tt>k2</tt> are considered equal if and only if
37 * <tt>(k1==k2)</tt>.  (In normal <tt>Map</tt> implementations (like
38 * <tt>HashMap</tt>) two keys <tt>k1</tt> and <tt>k2</tt> are considered equal
39 * if and only if <tt>(k1==null ? k2==null : k1.equals(k2))</tt>.)
40 *
41 * <p><b>This class is <i>not</i> a general-purpose <tt>Map</tt>
42 * implementation!  While this class implements the <tt>Map</tt> interface, it
43 * intentionally violates <tt>Map's</tt> general contract, which mandates the
44 * use of the <tt>equals</tt> method when comparing objects.  This class is
45 * designed for use only in the rare cases wherein reference-equality
46 * semantics are required.</b>
47 *
48 * <p>A typical use of this class is <i>topology-preserving object graph
49 * transformations</i>, such as serialization or deep-copying.  To perform such
50 * a transformation, a program must maintain a "node table" that keeps track
51 * of all the object references that have already been processed.  The node
52 * table must not equate distinct objects even if they happen to be equal.
53 * Another typical use of this class is to maintain <i>proxy objects</i>.  For
54 * example, a debugging facility might wish to maintain a proxy object for
55 * each object in the program being debugged.
56 *
57 * <p>This class provides all of the optional map operations, and permits
58 * <tt>null</tt> values and the <tt>null</tt> key.  This class makes no
59 * guarantees as to the order of the map; in particular, it does not guarantee
60 * that the order will remain constant over time.
61 *
62 * <p>This class provides constant-time performance for the basic
63 * operations (<tt>get</tt> and <tt>put</tt>), assuming the system
64 * identity hash function ({@link System#identityHashCode(Object)})
65 * disperses elements properly among the buckets.
66 *
67 * <p>This class has one tuning parameter (which affects performance but not
68 * semantics): <i>expected maximum size</i>.  This parameter is the maximum
69 * number of key-value mappings that the map is expected to hold.  Internally,
70 * this parameter is used to determine the number of buckets initially
71 * comprising the hash table.  The precise relationship between the expected
72 * maximum size and the number of buckets is unspecified.
73 *
74 * <p>If the size of the map (the number of key-value mappings) sufficiently
75 * exceeds the expected maximum size, the number of buckets is increased
76 * Increasing the number of buckets ("rehashing") may be fairly expensive, so
77 * it pays to create identity hash maps with a sufficiently large expected
78 * maximum size.  On the other hand, iteration over collection views requires
79 * time proportional to the number of buckets in the hash table, so it
80 * pays not to set the expected maximum size too high if you are especially
81 * concerned with iteration performance or memory usage.
82 *
83 * <p><strong>Note that this implementation is not synchronized.</strong>
84 * If multiple threads access an identity hash map concurrently, and at
85 * least one of the threads modifies the map structurally, it <i>must</i>
86 * be synchronized externally.  (A structural modification is any operation
87 * that adds or deletes one or more mappings; merely changing the value
88 * associated with a key that an instance already contains is not a
89 * structural modification.)  This is typically accomplished by
90 * synchronizing on some object that naturally encapsulates the map.
91 *
92 * If no such object exists, the map should be "wrapped" using the
93 * {@link Collections#synchronizedMap Collections.synchronizedMap}
94 * method.  This is best done at creation time, to prevent accidental
95 * unsynchronized access to the map:<pre>
96 *   Map m = Collections.synchronizedMap(new IdentityHashMap(...));</pre>
97 *
98 * <p>The iterators returned by the <tt>iterator</tt> method of the
99 * collections returned by all of this class's "collection view
100 * methods" are <i>fail-fast</i>: if the map is structurally modified
101 * at any time after the iterator is created, in any way except
102 * through the iterator's own <tt>remove</tt> method, the iterator
103 * will throw a {@link ConcurrentModificationException}.  Thus, in the
104 * face of concurrent modification, the iterator fails quickly and
105 * cleanly, rather than risking arbitrary, non-deterministic behavior
106 * at an undetermined time in the future.
107 *
108 * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
109 * as it is, generally speaking, impossible to make any hard guarantees in the
110 * presence of unsynchronized concurrent modification.  Fail-fast iterators
111 * throw <tt>ConcurrentModificationException</tt> on a best-effort basis.
112 * Therefore, it would be wrong to write a program that depended on this
113 * exception for its correctness: <i>fail-fast iterators should be used only
114 * to detect bugs.</i>
115 *
116 * <p>Implementation note: This is a simple <i>linear-probe</i> hash table,
117 * as described for example in texts by Sedgewick and Knuth.  The array
118 * alternates holding keys and values.  (This has better locality for large
119 * tables than does using separate arrays.)  For many JRE implementations
120 * and operation mixes, this class will yield better performance than
121 * {@link HashMap} (which uses <i>chaining</i> rather than linear-probing).
122 *
123 * <p>This class is a member of the
124 * <a href="{@docRoot}/../technotes/guides/collections/index.html">
125 * Java Collections Framework</a>.
126 *
127 * @see     System#identityHashCode(Object)
128 * @see     Object#hashCode()
129 * @see     Collection
130 * @see     Map
131 * @see     HashMap
132 * @see     TreeMap
133 * @author  Doug Lea and Josh Bloch
134 * @since   1.4
135 */
136
137public class IdentityHashMap<K,V>
138    extends AbstractMap<K,V>
139    implements Map<K,V>, java.io.Serializable, Cloneable
140{
141    /**
142     * The initial capacity used by the no-args constructor.
143     * MUST be a power of two.  The value 32 corresponds to the
144     * (specified) expected maximum size of 21, given a load factor
145     * of 2/3.
146     */
147    private static final int DEFAULT_CAPACITY = 32;
148
149    /**
150     * The minimum capacity, used if a lower value is implicitly specified
151     * by either of the constructors with arguments.  The value 4 corresponds
152     * to an expected maximum size of 2, given a load factor of 2/3.
153     * MUST be a power of two.
154     */
155    private static final int MINIMUM_CAPACITY = 4;
156
157    /**
158     * The maximum capacity, used if a higher value is implicitly specified
159     * by either of the constructors with arguments.
160     * MUST be a power of two <= 1<<29.
161     */
162    private static final int MAXIMUM_CAPACITY = 1 << 29;
163
164    /**
165     * The table, resized as necessary. Length MUST always be a power of two.
166     */
167    private transient Object[] table;
168
169    /**
170     * The number of key-value mappings contained in this identity hash map.
171     *
172     * @serial
173     */
174    private int size;
175
176    /**
177     * The number of modifications, to support fast-fail iterators
178     */
179    private transient int modCount;
180
181    /**
182     * The next size value at which to resize (capacity * load factor).
183     */
184    private transient int threshold;
185
186    /**
187     * Value representing null keys inside tables.
188     */
189    private static final Object NULL_KEY = new Object();
190
191    /**
192     * Use NULL_KEY for key if it is null.
193     */
194    private static Object maskNull(Object key) {
195        return (key == null ? NULL_KEY : key);
196    }
197
198    /**
199     * Returns internal representation of null key back to caller as null.
200     */
201    private static Object unmaskNull(Object key) {
202        return (key == NULL_KEY ? null : key);
203    }
204
205    /**
206     * Constructs a new, empty identity hash map with a default expected
207     * maximum size (21).
208     */
209    public IdentityHashMap() {
210        init(DEFAULT_CAPACITY);
211    }
212
213    /**
214     * Constructs a new, empty map with the specified expected maximum size.
215     * Putting more than the expected number of key-value mappings into
216     * the map may cause the internal data structure to grow, which may be
217     * somewhat time-consuming.
218     *
219     * @param expectedMaxSize the expected maximum size of the map
220     * @throws IllegalArgumentException if <tt>expectedMaxSize</tt> is negative
221     */
222    public IdentityHashMap(int expectedMaxSize) {
223        if (expectedMaxSize < 0)
224            throw new IllegalArgumentException("expectedMaxSize is negative: "
225                                               + expectedMaxSize);
226        init(capacity(expectedMaxSize));
227    }
228
229    /**
230     * Returns the appropriate capacity for the specified expected maximum
231     * size.  Returns the smallest power of two between MINIMUM_CAPACITY
232     * and MAXIMUM_CAPACITY, inclusive, that is greater than
233     * (3 * expectedMaxSize)/2, if such a number exists.  Otherwise
234     * returns MAXIMUM_CAPACITY.  If (3 * expectedMaxSize)/2 is negative, it
235     * is assumed that overflow has occurred, and MAXIMUM_CAPACITY is returned.
236     */
237    private int capacity(int expectedMaxSize) {
238        // Compute min capacity for expectedMaxSize given a load factor of 2/3
239        int minCapacity = (3 * expectedMaxSize)/2;
240
241        // Compute the appropriate capacity
242        int result;
243        if (minCapacity > MAXIMUM_CAPACITY || minCapacity < 0) {
244            result = MAXIMUM_CAPACITY;
245        } else {
246            result = MINIMUM_CAPACITY;
247            while (result < minCapacity)
248                result <<= 1;
249        }
250        return result;
251    }
252
253    /**
254     * Initializes object to be an empty map with the specified initial
255     * capacity, which is assumed to be a power of two between
256     * MINIMUM_CAPACITY and MAXIMUM_CAPACITY inclusive.
257     */
258    private void init(int initCapacity) {
259        // assert (initCapacity & -initCapacity) == initCapacity; // power of 2
260        // assert initCapacity >= MINIMUM_CAPACITY;
261        // assert initCapacity <= MAXIMUM_CAPACITY;
262
263        threshold = (initCapacity * 2)/3;
264        table = new Object[2 * initCapacity];
265    }
266
267    /**
268     * Constructs a new identity hash map containing the keys-value mappings
269     * in the specified map.
270     *
271     * @param m the map whose mappings are to be placed into this map
272     * @throws NullPointerException if the specified map is null
273     */
274    public IdentityHashMap(Map<? extends K, ? extends V> m) {
275        // Allow for a bit of growth
276        this((int) ((1 + m.size()) * 1.1));
277        putAll(m);
278    }
279
280    /**
281     * Returns the number of key-value mappings in this identity hash map.
282     *
283     * @return the number of key-value mappings in this map
284     */
285    public int size() {
286        return size;
287    }
288
289    /**
290     * Returns <tt>true</tt> if this identity hash map contains no key-value
291     * mappings.
292     *
293     * @return <tt>true</tt> if this identity hash map contains no key-value
294     *         mappings
295     */
296    public boolean isEmpty() {
297        return size == 0;
298    }
299
300    /**
301     * Returns index for Object x.
302     */
303    private static int hash(Object x, int length) {
304        int h = System.identityHashCode(x);
305        // Multiply by -127, and left-shift to use least bit as part of hash
306        return ((h << 1) - (h << 8)) & (length - 1);
307    }
308
309    /**
310     * Circularly traverses table of size len.
311     */
312    private static int nextKeyIndex(int i, int len) {
313        return (i + 2 < len ? i + 2 : 0);
314    }
315
316    /**
317     * Returns the value to which the specified key is mapped,
318     * or {@code null} if this map contains no mapping for the key.
319     *
320     * <p>More formally, if this map contains a mapping from a key
321     * {@code k} to a value {@code v} such that {@code (key == k)},
322     * then this method returns {@code v}; otherwise it returns
323     * {@code null}.  (There can be at most one such mapping.)
324     *
325     * <p>A return value of {@code null} does not <i>necessarily</i>
326     * indicate that the map contains no mapping for the key; it's also
327     * possible that the map explicitly maps the key to {@code null}.
328     * The {@link #containsKey containsKey} operation may be used to
329     * distinguish these two cases.
330     *
331     * @see #put(Object, Object)
332     */
333    public V get(Object key) {
334        Object k = maskNull(key);
335        Object[] tab = table;
336        int len = tab.length;
337        int i = hash(k, len);
338        while (true) {
339            Object item = tab[i];
340            if (item == k)
341                return (V) tab[i + 1];
342            if (item == null)
343                return null;
344            i = nextKeyIndex(i, len);
345        }
346    }
347
348    /**
349     * Tests whether the specified object reference is a key in this identity
350     * hash map.
351     *
352     * @param   key   possible key
353     * @return  <code>true</code> if the specified object reference is a key
354     *          in this map
355     * @see     #containsValue(Object)
356     */
357    public boolean containsKey(Object key) {
358        Object k = maskNull(key);
359        Object[] tab = table;
360        int len = tab.length;
361        int i = hash(k, len);
362        while (true) {
363            Object item = tab[i];
364            if (item == k)
365                return true;
366            if (item == null)
367                return false;
368            i = nextKeyIndex(i, len);
369        }
370    }
371
372    /**
373     * Tests whether the specified object reference is a value in this identity
374     * hash map.
375     *
376     * @param value value whose presence in this map is to be tested
377     * @return <tt>true</tt> if this map maps one or more keys to the
378     *         specified object reference
379     * @see     #containsKey(Object)
380     */
381    public boolean containsValue(Object value) {
382        Object[] tab = table;
383        for (int i = 1; i < tab.length; i += 2)
384            if (tab[i] == value && tab[i - 1] != null)
385                return true;
386
387        return false;
388    }
389
390    /**
391     * Tests if the specified key-value mapping is in the map.
392     *
393     * @param   key   possible key
394     * @param   value possible value
395     * @return  <code>true</code> if and only if the specified key-value
396     *          mapping is in the map
397     */
398    private boolean containsMapping(Object key, Object value) {
399        Object k = maskNull(key);
400        Object[] tab = table;
401        int len = tab.length;
402        int i = hash(k, len);
403        while (true) {
404            Object item = tab[i];
405            if (item == k)
406                return tab[i + 1] == value;
407            if (item == null)
408                return false;
409            i = nextKeyIndex(i, len);
410        }
411    }
412
413    /**
414     * Associates the specified value with the specified key in this identity
415     * hash map.  If the map previously contained a mapping for the key, the
416     * old value is replaced.
417     *
418     * @param key the key with which the specified value is to be associated
419     * @param value the value to be associated with the specified key
420     * @return the previous value associated with <tt>key</tt>, or
421     *         <tt>null</tt> if there was no mapping for <tt>key</tt>.
422     *         (A <tt>null</tt> return can also indicate that the map
423     *         previously associated <tt>null</tt> with <tt>key</tt>.)
424     * @see     Object#equals(Object)
425     * @see     #get(Object)
426     * @see     #containsKey(Object)
427     */
428    public V put(K key, V value) {
429        Object k = maskNull(key);
430        Object[] tab = table;
431        int len = tab.length;
432        int i = hash(k, len);
433
434        Object item;
435        while ( (item = tab[i]) != null) {
436            if (item == k) {
437                V oldValue = (V) tab[i + 1];
438                tab[i + 1] = value;
439                return oldValue;
440            }
441            i = nextKeyIndex(i, len);
442        }
443
444        modCount++;
445        tab[i] = k;
446        tab[i + 1] = value;
447        if (++size >= threshold)
448            resize(len); // len == 2 * current capacity.
449        return null;
450    }
451
452    /**
453     * Resize the table to hold given capacity.
454     *
455     * @param newCapacity the new capacity, must be a power of two.
456     */
457    private void resize(int newCapacity) {
458        // assert (newCapacity & -newCapacity) == newCapacity; // power of 2
459        int newLength = newCapacity * 2;
460
461        Object[] oldTable = table;
462        int oldLength = oldTable.length;
463        if (oldLength == 2*MAXIMUM_CAPACITY) { // can't expand any further
464            if (threshold == MAXIMUM_CAPACITY-1)
465                throw new IllegalStateException("Capacity exhausted.");
466            threshold = MAXIMUM_CAPACITY-1;  // Gigantic map!
467            return;
468        }
469        if (oldLength >= newLength)
470            return;
471
472        Object[] newTable = new Object[newLength];
473        threshold = newLength / 3;
474
475        for (int j = 0; j < oldLength; j += 2) {
476            Object key = oldTable[j];
477            if (key != null) {
478                Object value = oldTable[j+1];
479                oldTable[j] = null;
480                oldTable[j+1] = null;
481                int i = hash(key, newLength);
482                while (newTable[i] != null)
483                    i = nextKeyIndex(i, newLength);
484                newTable[i] = key;
485                newTable[i + 1] = value;
486            }
487        }
488        table = newTable;
489    }
490
491    /**
492     * Copies all of the mappings from the specified map to this map.
493     * These mappings will replace any mappings that this map had for
494     * any of the keys currently in the specified map.
495     *
496     * @param m mappings to be stored in this map
497     * @throws NullPointerException if the specified map is null
498     */
499    public void putAll(Map<? extends K, ? extends V> m) {
500        int n = m.size();
501        if (n == 0)
502            return;
503        if (n > threshold) // conservatively pre-expand
504            resize(capacity(n));
505
506        for (Entry<? extends K, ? extends V> e : m.entrySet())
507            put(e.getKey(), e.getValue());
508    }
509
510    /**
511     * Removes the mapping for this key from this map if present.
512     *
513     * @param key key whose mapping is to be removed from the map
514     * @return the previous value associated with <tt>key</tt>, or
515     *         <tt>null</tt> if there was no mapping for <tt>key</tt>.
516     *         (A <tt>null</tt> return can also indicate that the map
517     *         previously associated <tt>null</tt> with <tt>key</tt>.)
518     */
519    public V remove(Object key) {
520        Object k = maskNull(key);
521        Object[] tab = table;
522        int len = tab.length;
523        int i = hash(k, len);
524
525        while (true) {
526            Object item = tab[i];
527            if (item == k) {
528                modCount++;
529                size--;
530                V oldValue = (V) tab[i + 1];
531                tab[i + 1] = null;
532                tab[i] = null;
533                closeDeletion(i);
534                return oldValue;
535            }
536            if (item == null)
537                return null;
538            i = nextKeyIndex(i, len);
539        }
540
541    }
542
543    /**
544     * Removes the specified key-value mapping from the map if it is present.
545     *
546     * @param   key   possible key
547     * @param   value possible value
548     * @return  <code>true</code> if and only if the specified key-value
549     *          mapping was in the map
550     */
551    private boolean removeMapping(Object key, Object value) {
552        Object k = maskNull(key);
553        Object[] tab = table;
554        int len = tab.length;
555        int i = hash(k, len);
556
557        while (true) {
558            Object item = tab[i];
559            if (item == k) {
560                if (tab[i + 1] != value)
561                    return false;
562                modCount++;
563                size--;
564                tab[i] = null;
565                tab[i + 1] = null;
566                closeDeletion(i);
567                return true;
568            }
569            if (item == null)
570                return false;
571            i = nextKeyIndex(i, len);
572        }
573    }
574
575    /**
576     * Rehash all possibly-colliding entries following a
577     * deletion. This preserves the linear-probe
578     * collision properties required by get, put, etc.
579     *
580     * @param d the index of a newly empty deleted slot
581     */
582    private void closeDeletion(int d) {
583        // Adapted from Knuth Section 6.4 Algorithm R
584        Object[] tab = table;
585        int len = tab.length;
586
587        // Look for items to swap into newly vacated slot
588        // starting at index immediately following deletion,
589        // and continuing until a null slot is seen, indicating
590        // the end of a run of possibly-colliding keys.
591        Object item;
592        for (int i = nextKeyIndex(d, len); (item = tab[i]) != null;
593             i = nextKeyIndex(i, len) ) {
594            // The following test triggers if the item at slot i (which
595            // hashes to be at slot r) should take the spot vacated by d.
596            // If so, we swap it in, and then continue with d now at the
597            // newly vacated i.  This process will terminate when we hit
598            // the null slot at the end of this run.
599            // The test is messy because we are using a circular table.
600            int r = hash(item, len);
601            if ((i < r && (r <= d || d <= i)) || (r <= d && d <= i)) {
602                tab[d] = item;
603                tab[d + 1] = tab[i + 1];
604                tab[i] = null;
605                tab[i + 1] = null;
606                d = i;
607            }
608        }
609    }
610
611    /**
612     * Removes all of the mappings from this map.
613     * The map will be empty after this call returns.
614     */
615    public void clear() {
616        modCount++;
617        Object[] tab = table;
618        for (int i = 0; i < tab.length; i++)
619            tab[i] = null;
620        size = 0;
621    }
622
623    /**
624     * Compares the specified object with this map for equality.  Returns
625     * <tt>true</tt> if the given object is also a map and the two maps
626     * represent identical object-reference mappings.  More formally, this
627     * map is equal to another map <tt>m</tt> if and only if
628     * <tt>this.entrySet().equals(m.entrySet())</tt>.
629     *
630     * <p><b>Owing to the reference-equality-based semantics of this map it is
631     * possible that the symmetry and transitivity requirements of the
632     * <tt>Object.equals</tt> contract may be violated if this map is compared
633     * to a normal map.  However, the <tt>Object.equals</tt> contract is
634     * guaranteed to hold among <tt>IdentityHashMap</tt> instances.</b>
635     *
636     * @param  o object to be compared for equality with this map
637     * @return <tt>true</tt> if the specified object is equal to this map
638     * @see Object#equals(Object)
639     */
640    public boolean equals(Object o) {
641        if (o == this) {
642            return true;
643        } else if (o instanceof IdentityHashMap) {
644            IdentityHashMap m = (IdentityHashMap) o;
645            if (m.size() != size)
646                return false;
647
648            Object[] tab = m.table;
649            for (int i = 0; i < tab.length; i+=2) {
650                Object k = tab[i];
651                if (k != null && !containsMapping(k, tab[i + 1]))
652                    return false;
653            }
654            return true;
655        } else if (o instanceof Map) {
656            Map m = (Map)o;
657            return entrySet().equals(m.entrySet());
658        } else {
659            return false;  // o is not a Map
660        }
661    }
662
663    /**
664     * Returns the hash code value for this map.  The hash code of a map is
665     * defined to be the sum of the hash codes of each entry in the map's
666     * <tt>entrySet()</tt> view.  This ensures that <tt>m1.equals(m2)</tt>
667     * implies that <tt>m1.hashCode()==m2.hashCode()</tt> for any two
668     * <tt>IdentityHashMap</tt> instances <tt>m1</tt> and <tt>m2</tt>, as
669     * required by the general contract of {@link Object#hashCode}.
670     *
671     * <p><b>Owing to the reference-equality-based semantics of the
672     * <tt>Map.Entry</tt> instances in the set returned by this map's
673     * <tt>entrySet</tt> method, it is possible that the contractual
674     * requirement of <tt>Object.hashCode</tt> mentioned in the previous
675     * paragraph will be violated if one of the two objects being compared is
676     * an <tt>IdentityHashMap</tt> instance and the other is a normal map.</b>
677     *
678     * @return the hash code value for this map
679     * @see Object#equals(Object)
680     * @see #equals(Object)
681     */
682    public int hashCode() {
683        int result = 0;
684        Object[] tab = table;
685        for (int i = 0; i < tab.length; i +=2) {
686            Object key = tab[i];
687            if (key != null) {
688                Object k = unmaskNull(key);
689                result += System.identityHashCode(k) ^
690                          System.identityHashCode(tab[i + 1]);
691            }
692        }
693        return result;
694    }
695
696    /**
697     * Returns a shallow copy of this identity hash map: the keys and values
698     * themselves are not cloned.
699     *
700     * @return a shallow copy of this map
701     */
702    public Object clone() {
703        try {
704            IdentityHashMap<K,V> m = (IdentityHashMap<K,V>) super.clone();
705            m.entrySet = null;
706            m.table = table.clone();
707            return m;
708        } catch (CloneNotSupportedException e) {
709            throw new InternalError();
710        }
711    }
712
713    private abstract class IdentityHashMapIterator<T> implements Iterator<T> {
714        int index = (size != 0 ? 0 : table.length); // current slot.
715        int expectedModCount = modCount; // to support fast-fail
716        int lastReturnedIndex = -1;      // to allow remove()
717        boolean indexValid; // To avoid unnecessary next computation
718        Object[] traversalTable = table; // reference to main table or copy
719
720        public boolean hasNext() {
721            Object[] tab = traversalTable;
722            for (int i = index; i < tab.length; i+=2) {
723                Object key = tab[i];
724                if (key != null) {
725                    index = i;
726                    return indexValid = true;
727                }
728            }
729            index = tab.length;
730            return false;
731        }
732
733        protected int nextIndex() {
734            if (modCount != expectedModCount)
735                throw new ConcurrentModificationException();
736            if (!indexValid && !hasNext())
737                throw new NoSuchElementException();
738
739            indexValid = false;
740            lastReturnedIndex = index;
741            index += 2;
742            return lastReturnedIndex;
743        }
744
745        public void remove() {
746            if (lastReturnedIndex == -1)
747                throw new IllegalStateException();
748            if (modCount != expectedModCount)
749                throw new ConcurrentModificationException();
750
751            expectedModCount = ++modCount;
752            int deletedSlot = lastReturnedIndex;
753            lastReturnedIndex = -1;
754            // back up index to revisit new contents after deletion
755            index = deletedSlot;
756            indexValid = false;
757
758            // Removal code proceeds as in closeDeletion except that
759            // it must catch the rare case where an element already
760            // seen is swapped into a vacant slot that will be later
761            // traversed by this iterator. We cannot allow future
762            // next() calls to return it again.  The likelihood of
763            // this occurring under 2/3 load factor is very slim, but
764            // when it does happen, we must make a copy of the rest of
765            // the table to use for the rest of the traversal. Since
766            // this can only happen when we are near the end of the table,
767            // even in these rare cases, this is not very expensive in
768            // time or space.
769
770            Object[] tab = traversalTable;
771            int len = tab.length;
772
773            int d = deletedSlot;
774            K key = (K) tab[d];
775            tab[d] = null;        // vacate the slot
776            tab[d + 1] = null;
777
778            // If traversing a copy, remove in real table.
779            // We can skip gap-closure on copy.
780            if (tab != IdentityHashMap.this.table) {
781                IdentityHashMap.this.remove(key);
782                expectedModCount = modCount;
783                return;
784            }
785
786            size--;
787
788            Object item;
789            for (int i = nextKeyIndex(d, len); (item = tab[i]) != null;
790                 i = nextKeyIndex(i, len)) {
791                int r = hash(item, len);
792                // See closeDeletion for explanation of this conditional
793                if ((i < r && (r <= d || d <= i)) ||
794                    (r <= d && d <= i)) {
795
796                    // If we are about to swap an already-seen element
797                    // into a slot that may later be returned by next(),
798                    // then clone the rest of table for use in future
799                    // next() calls. It is OK that our copy will have
800                    // a gap in the "wrong" place, since it will never
801                    // be used for searching anyway.
802
803                    if (i < deletedSlot && d >= deletedSlot &&
804                        traversalTable == IdentityHashMap.this.table) {
805                        int remaining = len - deletedSlot;
806                        Object[] newTable = new Object[remaining];
807                        System.arraycopy(tab, deletedSlot,
808                                         newTable, 0, remaining);
809                        traversalTable = newTable;
810                        index = 0;
811                    }
812
813                    tab[d] = item;
814                    tab[d + 1] = tab[i + 1];
815                    tab[i] = null;
816                    tab[i + 1] = null;
817                    d = i;
818                }
819            }
820        }
821    }
822
823    private class KeyIterator extends IdentityHashMapIterator<K> {
824        public K next() {
825            return (K) unmaskNull(traversalTable[nextIndex()]);
826        }
827    }
828
829    private class ValueIterator extends IdentityHashMapIterator<V> {
830        public V next() {
831            return (V) traversalTable[nextIndex() + 1];
832        }
833    }
834
835    private class EntryIterator
836        extends IdentityHashMapIterator<Map.Entry<K,V>>
837    {
838        private Entry lastReturnedEntry = null;
839
840        public Map.Entry<K,V> next() {
841            lastReturnedEntry = new Entry(nextIndex());
842            return lastReturnedEntry;
843        }
844
845        public void remove() {
846            lastReturnedIndex =
847                ((null == lastReturnedEntry) ? -1 : lastReturnedEntry.index);
848            super.remove();
849            lastReturnedEntry.index = lastReturnedIndex;
850            lastReturnedEntry = null;
851        }
852
853        private class Entry implements Map.Entry<K,V> {
854            private int index;
855
856            private Entry(int index) {
857                this.index = index;
858            }
859
860            public K getKey() {
861                checkIndexForEntryUse();
862                return (K) unmaskNull(traversalTable[index]);
863            }
864
865            public V getValue() {
866                checkIndexForEntryUse();
867                return (V) traversalTable[index+1];
868            }
869
870            public V setValue(V value) {
871                checkIndexForEntryUse();
872                V oldValue = (V) traversalTable[index+1];
873                traversalTable[index+1] = value;
874                // if shadowing, force into main table
875                if (traversalTable != IdentityHashMap.this.table)
876                    put((K) traversalTable[index], value);
877                return oldValue;
878            }
879
880            public boolean equals(Object o) {
881                if (index < 0)
882                    return super.equals(o);
883
884                if (!(o instanceof Map.Entry))
885                    return false;
886                Map.Entry e = (Map.Entry)o;
887                return (e.getKey() == unmaskNull(traversalTable[index]) &&
888                       e.getValue() == traversalTable[index+1]);
889            }
890
891            public int hashCode() {
892                if (lastReturnedIndex < 0)
893                    return super.hashCode();
894
895                return (System.identityHashCode(unmaskNull(traversalTable[index])) ^
896                       System.identityHashCode(traversalTable[index+1]));
897            }
898
899            public String toString() {
900                if (index < 0)
901                    return super.toString();
902
903                return (unmaskNull(traversalTable[index]) + "="
904                        + traversalTable[index+1]);
905            }
906
907            private void checkIndexForEntryUse() {
908                if (index < 0)
909                    throw new IllegalStateException("Entry was removed");
910            }
911        }
912    }
913
914    // Views
915
916    /**
917     * This field is initialized to contain an instance of the entry set
918     * view the first time this view is requested.  The view is stateless,
919     * so there's no reason to create more than one.
920     */
921    private transient Set<Map.Entry<K,V>> entrySet = null;
922
923    /**
924     * Returns an identity-based set view of the keys contained in this map.
925     * The set is backed by the map, so changes to the map are reflected in
926     * the set, and vice-versa.  If the map is modified while an iteration
927     * over the set is in progress, the results of the iteration are
928     * undefined.  The set supports element removal, which removes the
929     * corresponding mapping from the map, via the <tt>Iterator.remove</tt>,
930     * <tt>Set.remove</tt>, <tt>removeAll</tt>, <tt>retainAll</tt>, and
931     * <tt>clear</tt> methods.  It does not support the <tt>add</tt> or
932     * <tt>addAll</tt> methods.
933     *
934     * <p><b>While the object returned by this method implements the
935     * <tt>Set</tt> interface, it does <i>not</i> obey <tt>Set's</tt> general
936     * contract.  Like its backing map, the set returned by this method
937     * defines element equality as reference-equality rather than
938     * object-equality.  This affects the behavior of its <tt>contains</tt>,
939     * <tt>remove</tt>, <tt>containsAll</tt>, <tt>equals</tt>, and
940     * <tt>hashCode</tt> methods.</b>
941     *
942     * <p><b>The <tt>equals</tt> method of the returned set returns <tt>true</tt>
943     * only if the specified object is a set containing exactly the same
944     * object references as the returned set.  The symmetry and transitivity
945     * requirements of the <tt>Object.equals</tt> contract may be violated if
946     * the set returned by this method is compared to a normal set.  However,
947     * the <tt>Object.equals</tt> contract is guaranteed to hold among sets
948     * returned by this method.</b>
949     *
950     * <p>The <tt>hashCode</tt> method of the returned set returns the sum of
951     * the <i>identity hashcodes</i> of the elements in the set, rather than
952     * the sum of their hashcodes.  This is mandated by the change in the
953     * semantics of the <tt>equals</tt> method, in order to enforce the
954     * general contract of the <tt>Object.hashCode</tt> method among sets
955     * returned by this method.
956     *
957     * @return an identity-based set view of the keys contained in this map
958     * @see Object#equals(Object)
959     * @see System#identityHashCode(Object)
960     */
961    public Set<K> keySet() {
962        Set<K> ks = keySet;
963        if (ks != null)
964            return ks;
965        else
966            return keySet = new KeySet();
967    }
968
969    private class KeySet extends AbstractSet<K> {
970        public Iterator<K> iterator() {
971            return new KeyIterator();
972        }
973        public int size() {
974            return size;
975        }
976        public boolean contains(Object o) {
977            return containsKey(o);
978        }
979        public boolean remove(Object o) {
980            int oldSize = size;
981            IdentityHashMap.this.remove(o);
982            return size != oldSize;
983        }
984        /*
985         * Must revert from AbstractSet's impl to AbstractCollection's, as
986         * the former contains an optimization that results in incorrect
987         * behavior when c is a smaller "normal" (non-identity-based) Set.
988         */
989        public boolean removeAll(Collection<?> c) {
990            boolean modified = false;
991            for (Iterator<K> i = iterator(); i.hasNext(); ) {
992                if (c.contains(i.next())) {
993                    i.remove();
994                    modified = true;
995                }
996            }
997            return modified;
998        }
999        public void clear() {
1000            IdentityHashMap.this.clear();
1001        }
1002        public int hashCode() {
1003            int result = 0;
1004            for (K key : this)
1005                result += System.identityHashCode(key);
1006            return result;
1007        }
1008    }
1009
1010    /**
1011     * Returns a {@link Collection} view of the values contained in this map.
1012     * The collection is backed by the map, so changes to the map are
1013     * reflected in the collection, and vice-versa.  If the map is
1014     * modified while an iteration over the collection is in progress,
1015     * the results of the iteration are undefined.  The collection
1016     * supports element removal, which removes the corresponding
1017     * mapping from the map, via the <tt>Iterator.remove</tt>,
1018     * <tt>Collection.remove</tt>, <tt>removeAll</tt>,
1019     * <tt>retainAll</tt> and <tt>clear</tt> methods.  It does not
1020     * support the <tt>add</tt> or <tt>addAll</tt> methods.
1021     *
1022     * <p><b>While the object returned by this method implements the
1023     * <tt>Collection</tt> interface, it does <i>not</i> obey
1024     * <tt>Collection's</tt> general contract.  Like its backing map,
1025     * the collection returned by this method defines element equality as
1026     * reference-equality rather than object-equality.  This affects the
1027     * behavior of its <tt>contains</tt>, <tt>remove</tt> and
1028     * <tt>containsAll</tt> methods.</b>
1029     */
1030    public Collection<V> values() {
1031        Collection<V> vs = values;
1032        if (vs != null)
1033            return vs;
1034        else
1035            return values = new Values();
1036    }
1037
1038    private class Values extends AbstractCollection<V> {
1039        public Iterator<V> iterator() {
1040            return new ValueIterator();
1041        }
1042        public int size() {
1043            return size;
1044        }
1045        public boolean contains(Object o) {
1046            return containsValue(o);
1047        }
1048        public boolean remove(Object o) {
1049            for (Iterator<V> i = iterator(); i.hasNext(); ) {
1050                if (i.next() == o) {
1051                    i.remove();
1052                    return true;
1053                }
1054            }
1055            return false;
1056        }
1057        public void clear() {
1058            IdentityHashMap.this.clear();
1059        }
1060    }
1061
1062    /**
1063     * Returns a {@link Set} view of the mappings contained in this map.
1064     * Each element in the returned set is a reference-equality-based
1065     * <tt>Map.Entry</tt>.  The set is backed by the map, so changes
1066     * to the map are reflected in the set, and vice-versa.  If the
1067     * map is modified while an iteration over the set is in progress,
1068     * the results of the iteration are undefined.  The set supports
1069     * element removal, which removes the corresponding mapping from
1070     * the map, via the <tt>Iterator.remove</tt>, <tt>Set.remove</tt>,
1071     * <tt>removeAll</tt>, <tt>retainAll</tt> and <tt>clear</tt>
1072     * methods.  It does not support the <tt>add</tt> or
1073     * <tt>addAll</tt> methods.
1074     *
1075     * <p>Like the backing map, the <tt>Map.Entry</tt> objects in the set
1076     * returned by this method define key and value equality as
1077     * reference-equality rather than object-equality.  This affects the
1078     * behavior of the <tt>equals</tt> and <tt>hashCode</tt> methods of these
1079     * <tt>Map.Entry</tt> objects.  A reference-equality based <tt>Map.Entry
1080     * e</tt> is equal to an object <tt>o</tt> if and only if <tt>o</tt> is a
1081     * <tt>Map.Entry</tt> and <tt>e.getKey()==o.getKey() &amp;&amp;
1082     * e.getValue()==o.getValue()</tt>.  To accommodate these equals
1083     * semantics, the <tt>hashCode</tt> method returns
1084     * <tt>System.identityHashCode(e.getKey()) ^
1085     * System.identityHashCode(e.getValue())</tt>.
1086     *
1087     * <p><b>Owing to the reference-equality-based semantics of the
1088     * <tt>Map.Entry</tt> instances in the set returned by this method,
1089     * it is possible that the symmetry and transitivity requirements of
1090     * the {@link Object#equals(Object)} contract may be violated if any of
1091     * the entries in the set is compared to a normal map entry, or if
1092     * the set returned by this method is compared to a set of normal map
1093     * entries (such as would be returned by a call to this method on a normal
1094     * map).  However, the <tt>Object.equals</tt> contract is guaranteed to
1095     * hold among identity-based map entries, and among sets of such entries.
1096     * </b>
1097     *
1098     * @return a set view of the identity-mappings contained in this map
1099     */
1100    public Set<Map.Entry<K,V>> entrySet() {
1101        Set<Map.Entry<K,V>> es = entrySet;
1102        if (es != null)
1103            return es;
1104        else
1105            return entrySet = new EntrySet();
1106    }
1107
1108    private class EntrySet extends AbstractSet<Map.Entry<K,V>> {
1109        public Iterator<Map.Entry<K,V>> iterator() {
1110            return new EntryIterator();
1111        }
1112        public boolean contains(Object o) {
1113            if (!(o instanceof Map.Entry))
1114                return false;
1115            Map.Entry entry = (Map.Entry)o;
1116            return containsMapping(entry.getKey(), entry.getValue());
1117        }
1118        public boolean remove(Object o) {
1119            if (!(o instanceof Map.Entry))
1120                return false;
1121            Map.Entry entry = (Map.Entry)o;
1122            return removeMapping(entry.getKey(), entry.getValue());
1123        }
1124        public int size() {
1125            return size;
1126        }
1127        public void clear() {
1128            IdentityHashMap.this.clear();
1129        }
1130        /*
1131         * Must revert from AbstractSet's impl to AbstractCollection's, as
1132         * the former contains an optimization that results in incorrect
1133         * behavior when c is a smaller "normal" (non-identity-based) Set.
1134         */
1135        public boolean removeAll(Collection<?> c) {
1136            boolean modified = false;
1137            for (Iterator<Map.Entry<K,V>> i = iterator(); i.hasNext(); ) {
1138                if (c.contains(i.next())) {
1139                    i.remove();
1140                    modified = true;
1141                }
1142            }
1143            return modified;
1144        }
1145
1146        public Object[] toArray() {
1147            int size = size();
1148            Object[] result = new Object[size];
1149            Iterator<Map.Entry<K,V>> it = iterator();
1150            for (int i = 0; i < size; i++)
1151                result[i] = new AbstractMap.SimpleEntry<>(it.next());
1152            return result;
1153        }
1154
1155        @SuppressWarnings("unchecked")
1156        public <T> T[] toArray(T[] a) {
1157            int size = size();
1158            if (a.length < size)
1159                a = (T[])java.lang.reflect.Array
1160                    .newInstance(a.getClass().getComponentType(), size);
1161            Iterator<Map.Entry<K,V>> it = iterator();
1162            for (int i = 0; i < size; i++)
1163                a[i] = (T) new AbstractMap.SimpleEntry<>(it.next());
1164            if (a.length > size)
1165                a[size] = null;
1166            return a;
1167        }
1168    }
1169
1170
1171    private static final long serialVersionUID = 8188218128353913216L;
1172
1173    /**
1174     * Save the state of the <tt>IdentityHashMap</tt> instance to a stream
1175     * (i.e., serialize it).
1176     *
1177     * @serialData The <i>size</i> of the HashMap (the number of key-value
1178     *          mappings) (<tt>int</tt>), followed by the key (Object) and
1179     *          value (Object) for each key-value mapping represented by the
1180     *          IdentityHashMap.  The key-value mappings are emitted in no
1181     *          particular order.
1182     */
1183    private void writeObject(java.io.ObjectOutputStream s)
1184        throws java.io.IOException  {
1185        // Write out and any hidden stuff
1186        s.defaultWriteObject();
1187
1188        // Write out size (number of Mappings)
1189        s.writeInt(size);
1190
1191        // Write out keys and values (alternating)
1192        Object[] tab = table;
1193        for (int i = 0; i < tab.length; i += 2) {
1194            Object key = tab[i];
1195            if (key != null) {
1196                s.writeObject(unmaskNull(key));
1197                s.writeObject(tab[i + 1]);
1198            }
1199        }
1200    }
1201
1202    /**
1203     * Reconstitute the <tt>IdentityHashMap</tt> instance from a stream (i.e.,
1204     * deserialize it).
1205     */
1206    private void readObject(java.io.ObjectInputStream s)
1207        throws java.io.IOException, ClassNotFoundException  {
1208        // Read in any hidden stuff
1209        s.defaultReadObject();
1210
1211        // Read in size (number of Mappings)
1212        int size = s.readInt();
1213
1214        // Allow for 33% growth (i.e., capacity is >= 2* size()).
1215        init(capacity((size*4)/3));
1216
1217        // Read the keys and values, and put the mappings in the table
1218        for (int i=0; i<size; i++) {
1219            K key = (K) s.readObject();
1220            V value = (V) s.readObject();
1221            putForCreate(key, value);
1222        }
1223    }
1224
1225    /**
1226     * The put method for readObject.  It does not resize the table,
1227     * update modCount, etc.
1228     */
1229    private void putForCreate(K key, V value)
1230        throws IOException
1231    {
1232        K k = (K)maskNull(key);
1233        Object[] tab = table;
1234        int len = tab.length;
1235        int i = hash(k, len);
1236
1237        Object item;
1238        while ( (item = tab[i]) != null) {
1239            if (item == k)
1240                throw new java.io.StreamCorruptedException();
1241            i = nextKeyIndex(i, len);
1242        }
1243        tab[i] = k;
1244        tab[i + 1] = value;
1245    }
1246
1247    @SuppressWarnings("unchecked")
1248    @Override
1249    public void forEach(BiConsumer<? super K, ? super V> action) {
1250        Objects.requireNonNull(action);
1251        int expectedModCount = modCount;
1252
1253        Object[] t = table;
1254        for (int index = 0; index < t.length; index += 2) {
1255            Object k = t[index];
1256            if (k != null) {
1257                action.accept((K) unmaskNull(k), (V) t[index + 1]);
1258            }
1259
1260            if (modCount != expectedModCount) {
1261                throw new ConcurrentModificationException();
1262            }
1263        }
1264    }
1265
1266}
1267