jdk/src/share/classes/java/util/HashMap.java
author mduigou
Wed, 30 May 2012 22:18:37 -0700
changeset 12859 c44b88bb9b5e
parent 12448 b95438b17098
child 12863 77e41e310650
permissions -rw-r--r--
7126277: Alternative String hashing implementation Summary: All of the hashing based Map implementations: HashMap, Hashtable, LinkedHashMap, WeakHashMap and ConcurrentHashMap are modified to use an enhanced hashing algorithm for string keys when the capacity of the hash table has ever grown beyond 512 entries. The enhanced hashing implementation uses the murmur3 hashing algorithm along with random hash seeds and index masks. These enhancements mitigate cases where colliding String hash values could result in a performance bottleneck. Reviewed-by: alanb, forax, dl
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
9035
1255eb81cc2f 7033660: Update copyright year to 2011 on any files changed in 2011
ohair
parents: 7803
diff changeset
     2
 * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     4
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
90ce3da70b43 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 4110
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 4110
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    10
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
90ce3da70b43 Initial load
duke
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
90ce3da70b43 Initial load
duke
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
90ce3da70b43 Initial load
duke
parents:
diff changeset
    15
 * accompanied this code).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    16
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
90ce3da70b43 Initial load
duke
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    20
 *
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 4110
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 4110
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 4110
diff changeset
    23
 * questions.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
90ce3da70b43 Initial load
duke
parents:
diff changeset
    26
package java.util;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    27
import java.io.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    28
90ce3da70b43 Initial load
duke
parents:
diff changeset
    29
/**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    30
 * Hash table based implementation of the <tt>Map</tt> interface.  This
90ce3da70b43 Initial load
duke
parents:
diff changeset
    31
 * implementation provides all of the optional map operations, and permits
90ce3da70b43 Initial load
duke
parents:
diff changeset
    32
 * <tt>null</tt> values and the <tt>null</tt> key.  (The <tt>HashMap</tt>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    33
 * class is roughly equivalent to <tt>Hashtable</tt>, except that it is
90ce3da70b43 Initial load
duke
parents:
diff changeset
    34
 * unsynchronized and permits nulls.)  This class makes no guarantees as to
90ce3da70b43 Initial load
duke
parents:
diff changeset
    35
 * the order of the map; in particular, it does not guarantee that the order
90ce3da70b43 Initial load
duke
parents:
diff changeset
    36
 * will remain constant over time.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    37
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    38
 * <p>This implementation provides constant-time performance for the basic
90ce3da70b43 Initial load
duke
parents:
diff changeset
    39
 * operations (<tt>get</tt> and <tt>put</tt>), assuming the hash function
90ce3da70b43 Initial load
duke
parents:
diff changeset
    40
 * disperses the elements properly among the buckets.  Iteration over
90ce3da70b43 Initial load
duke
parents:
diff changeset
    41
 * collection views requires time proportional to the "capacity" of the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    42
 * <tt>HashMap</tt> instance (the number of buckets) plus its size (the number
90ce3da70b43 Initial load
duke
parents:
diff changeset
    43
 * of key-value mappings).  Thus, it's very important not to set the initial
90ce3da70b43 Initial load
duke
parents:
diff changeset
    44
 * capacity too high (or the load factor too low) if iteration performance is
90ce3da70b43 Initial load
duke
parents:
diff changeset
    45
 * important.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    46
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    47
 * <p>An instance of <tt>HashMap</tt> has two parameters that affect its
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
 * performance: <i>initial capacity</i> and <i>load factor</i>.  The
90ce3da70b43 Initial load
duke
parents:
diff changeset
    49
 * <i>capacity</i> is the number of buckets in the hash table, and the initial
90ce3da70b43 Initial load
duke
parents:
diff changeset
    50
 * capacity is simply the capacity at the time the hash table is created.  The
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
 * <i>load factor</i> is a measure of how full the hash table is allowed to
90ce3da70b43 Initial load
duke
parents:
diff changeset
    52
 * get before its capacity is automatically increased.  When the number of
90ce3da70b43 Initial load
duke
parents:
diff changeset
    53
 * entries in the hash table exceeds the product of the load factor and the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    54
 * current capacity, the hash table is <i>rehashed</i> (that is, internal data
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
 * structures are rebuilt) so that the hash table has approximately twice the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    56
 * number of buckets.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
 * <p>As a general rule, the default load factor (.75) offers a good tradeoff
90ce3da70b43 Initial load
duke
parents:
diff changeset
    59
 * between time and space costs.  Higher values decrease the space overhead
90ce3da70b43 Initial load
duke
parents:
diff changeset
    60
 * but increase the lookup cost (reflected in most of the operations of the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    61
 * <tt>HashMap</tt> class, including <tt>get</tt> and <tt>put</tt>).  The
90ce3da70b43 Initial load
duke
parents:
diff changeset
    62
 * expected number of entries in the map and its load factor should be taken
90ce3da70b43 Initial load
duke
parents:
diff changeset
    63
 * into account when setting its initial capacity, so as to minimize the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    64
 * number of rehash operations.  If the initial capacity is greater
90ce3da70b43 Initial load
duke
parents:
diff changeset
    65
 * than the maximum number of entries divided by the load factor, no
90ce3da70b43 Initial load
duke
parents:
diff changeset
    66
 * rehash operations will ever occur.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
 * <p>If many mappings are to be stored in a <tt>HashMap</tt> instance,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    69
 * creating it with a sufficiently large capacity will allow the mappings to
90ce3da70b43 Initial load
duke
parents:
diff changeset
    70
 * be stored more efficiently than letting it perform automatic rehashing as
90ce3da70b43 Initial load
duke
parents:
diff changeset
    71
 * needed to grow the table.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    72
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    73
 * <p><strong>Note that this implementation is not synchronized.</strong>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
 * If multiple threads access a hash map concurrently, and at least one of
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
 * the threads modifies the map structurally, it <i>must</i> be
90ce3da70b43 Initial load
duke
parents:
diff changeset
    76
 * synchronized externally.  (A structural modification is any operation
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
 * that adds or deletes one or more mappings; merely changing the value
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
 * associated with a key that an instance already contains is not a
90ce3da70b43 Initial load
duke
parents:
diff changeset
    79
 * structural modification.)  This is typically accomplished by
90ce3da70b43 Initial load
duke
parents:
diff changeset
    80
 * synchronizing on some object that naturally encapsulates the map.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    81
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    82
 * If no such object exists, the map should be "wrapped" using the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    83
 * {@link Collections#synchronizedMap Collections.synchronizedMap}
90ce3da70b43 Initial load
duke
parents:
diff changeset
    84
 * method.  This is best done at creation time, to prevent accidental
90ce3da70b43 Initial load
duke
parents:
diff changeset
    85
 * unsynchronized access to the map:<pre>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    86
 *   Map m = Collections.synchronizedMap(new HashMap(...));</pre>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    87
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    88
 * <p>The iterators returned by all of this class's "collection view methods"
90ce3da70b43 Initial load
duke
parents:
diff changeset
    89
 * are <i>fail-fast</i>: if the map is structurally modified at any time after
90ce3da70b43 Initial load
duke
parents:
diff changeset
    90
 * the iterator is created, in any way except through the iterator's own
90ce3da70b43 Initial load
duke
parents:
diff changeset
    91
 * <tt>remove</tt> method, the iterator will throw a
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
 * {@link ConcurrentModificationException}.  Thus, in the face of concurrent
90ce3da70b43 Initial load
duke
parents:
diff changeset
    93
 * modification, the iterator fails quickly and cleanly, rather than risking
90ce3da70b43 Initial load
duke
parents:
diff changeset
    94
 * arbitrary, non-deterministic behavior at an undetermined time in the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    95
 * future.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    96
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    97
 * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
 * as it is, generally speaking, impossible to make any hard guarantees in the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    99
 * presence of unsynchronized concurrent modification.  Fail-fast iterators
90ce3da70b43 Initial load
duke
parents:
diff changeset
   100
 * throw <tt>ConcurrentModificationException</tt> on a best-effort basis.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
 * Therefore, it would be wrong to write a program that depended on this
90ce3da70b43 Initial load
duke
parents:
diff changeset
   102
 * exception for its correctness: <i>the fail-fast behavior of iterators
90ce3da70b43 Initial load
duke
parents:
diff changeset
   103
 * should be used only to detect bugs.</i>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   105
 * <p>This class is a member of the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   106
 * <a href="{@docRoot}/../technotes/guides/collections/index.html">
90ce3da70b43 Initial load
duke
parents:
diff changeset
   107
 * Java Collections Framework</a>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   108
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   109
 * @param <K> the type of keys maintained by this map
90ce3da70b43 Initial load
duke
parents:
diff changeset
   110
 * @param <V> the type of mapped values
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   112
 * @author  Doug Lea
90ce3da70b43 Initial load
duke
parents:
diff changeset
   113
 * @author  Josh Bloch
90ce3da70b43 Initial load
duke
parents:
diff changeset
   114
 * @author  Arthur van Hoff
90ce3da70b43 Initial load
duke
parents:
diff changeset
   115
 * @author  Neal Gafter
90ce3da70b43 Initial load
duke
parents:
diff changeset
   116
 * @see     Object#hashCode()
90ce3da70b43 Initial load
duke
parents:
diff changeset
   117
 * @see     Collection
90ce3da70b43 Initial load
duke
parents:
diff changeset
   118
 * @see     Map
90ce3da70b43 Initial load
duke
parents:
diff changeset
   119
 * @see     TreeMap
90ce3da70b43 Initial load
duke
parents:
diff changeset
   120
 * @see     Hashtable
90ce3da70b43 Initial load
duke
parents:
diff changeset
   121
 * @since   1.2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   122
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   123
90ce3da70b43 Initial load
duke
parents:
diff changeset
   124
public class HashMap<K,V>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   125
    extends AbstractMap<K,V>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   126
    implements Map<K,V>, Cloneable, Serializable
90ce3da70b43 Initial load
duke
parents:
diff changeset
   127
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   128
90ce3da70b43 Initial load
duke
parents:
diff changeset
   129
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   130
     * The default initial capacity - MUST be a power of two.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   131
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   132
    static final int DEFAULT_INITIAL_CAPACITY = 16;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   133
90ce3da70b43 Initial load
duke
parents:
diff changeset
   134
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   135
     * The maximum capacity, used if a higher value is implicitly specified
90ce3da70b43 Initial load
duke
parents:
diff changeset
   136
     * by either of the constructors with arguments.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   137
     * MUST be a power of two <= 1<<30.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   138
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   139
    static final int MAXIMUM_CAPACITY = 1 << 30;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   140
90ce3da70b43 Initial load
duke
parents:
diff changeset
   141
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   142
     * The load factor used when none specified in constructor.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   143
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   144
    static final float DEFAULT_LOAD_FACTOR = 0.75f;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   145
90ce3da70b43 Initial load
duke
parents:
diff changeset
   146
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   147
     * The table, resized as necessary. Length MUST Always be a power of two.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   148
     */
12448
b95438b17098 7157893: Warnings Cleanup in java.util.*
khazra
parents: 9035
diff changeset
   149
    transient Entry<?,?>[] table;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   150
90ce3da70b43 Initial load
duke
parents:
diff changeset
   151
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   152
     * The number of key-value mappings contained in this map.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   153
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   154
    transient int size;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   155
90ce3da70b43 Initial load
duke
parents:
diff changeset
   156
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   157
     * The next size value at which to resize (capacity * load factor).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   158
     * @serial
90ce3da70b43 Initial load
duke
parents:
diff changeset
   159
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   160
    int threshold;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   161
90ce3da70b43 Initial load
duke
parents:
diff changeset
   162
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   163
     * The load factor for the hash table.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   164
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   165
     * @serial
90ce3da70b43 Initial load
duke
parents:
diff changeset
   166
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   167
    final float loadFactor;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   168
90ce3da70b43 Initial load
duke
parents:
diff changeset
   169
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   170
     * The number of times this HashMap has been structurally modified
90ce3da70b43 Initial load
duke
parents:
diff changeset
   171
     * Structural modifications are those that change the number of mappings in
90ce3da70b43 Initial load
duke
parents:
diff changeset
   172
     * the HashMap or otherwise modify its internal structure (e.g.,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   173
     * rehash).  This field is used to make iterators on Collection-views of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   174
     * the HashMap fail-fast.  (See ConcurrentModificationException).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   175
     */
65
51fc1d79463f 6625725: (coll) modCount should not be volatile
martin
parents: 2
diff changeset
   176
    transient int modCount;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   177
12859
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   178
    private static class Holder {
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   179
         /**
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   180
         *
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   181
         */
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   182
        static final sun.misc.Unsafe UNSAFE;
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   183
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   184
        /**
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   185
         * Offset of "final" hashSeed field we must set in
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   186
         * readObject() method.
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   187
         */
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   188
        static final long HASHSEED_OFFSET;
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   189
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   190
        static {
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   191
            try {
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   192
                UNSAFE = sun.misc.Unsafe.getUnsafe();
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   193
                HASHSEED_OFFSET = UNSAFE.objectFieldOffset(
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   194
                    HashMap.class.getDeclaredField("hashSeed"));
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   195
            } catch (NoSuchFieldException | SecurityException e) {
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   196
                throw new InternalError("Failed to record hashSeed offset", e);
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   197
            }
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   198
        }
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   199
    }
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   200
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   201
    /**
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   202
     * A randomizing value associated with this instance that is applied to
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   203
     * hash code of keys to make hash collisions harder to find.
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   204
     */
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   205
    transient final int hashSeed = sun.misc.Hashing.randomHashSeed(this);
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   206
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   207
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   208
     * Constructs an empty <tt>HashMap</tt> with the specified initial
90ce3da70b43 Initial load
duke
parents:
diff changeset
   209
     * capacity and load factor.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   210
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   211
     * @param  initialCapacity the initial capacity
90ce3da70b43 Initial load
duke
parents:
diff changeset
   212
     * @param  loadFactor      the load factor
90ce3da70b43 Initial load
duke
parents:
diff changeset
   213
     * @throws IllegalArgumentException if the initial capacity is negative
90ce3da70b43 Initial load
duke
parents:
diff changeset
   214
     *         or the load factor is nonpositive
90ce3da70b43 Initial load
duke
parents:
diff changeset
   215
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   216
    public HashMap(int initialCapacity, float loadFactor) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   217
        if (initialCapacity < 0)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   218
            throw new IllegalArgumentException("Illegal initial capacity: " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   219
                                               initialCapacity);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   220
        if (initialCapacity > MAXIMUM_CAPACITY)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   221
            initialCapacity = MAXIMUM_CAPACITY;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   222
        if (loadFactor <= 0 || Float.isNaN(loadFactor))
90ce3da70b43 Initial load
duke
parents:
diff changeset
   223
            throw new IllegalArgumentException("Illegal load factor: " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   224
                                               loadFactor);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   225
90ce3da70b43 Initial load
duke
parents:
diff changeset
   226
        // Find a power of 2 >= initialCapacity
90ce3da70b43 Initial load
duke
parents:
diff changeset
   227
        int capacity = 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   228
        while (capacity < initialCapacity)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   229
            capacity <<= 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   230
90ce3da70b43 Initial load
duke
parents:
diff changeset
   231
        this.loadFactor = loadFactor;
12859
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   232
        threshold = (int)Math.min(capacity * loadFactor, MAXIMUM_CAPACITY + 1);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   233
        table = new Entry[capacity];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   234
        init();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   235
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   236
90ce3da70b43 Initial load
duke
parents:
diff changeset
   237
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   238
     * Constructs an empty <tt>HashMap</tt> with the specified initial
90ce3da70b43 Initial load
duke
parents:
diff changeset
   239
     * capacity and the default load factor (0.75).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   240
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   241
     * @param  initialCapacity the initial capacity.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   242
     * @throws IllegalArgumentException if the initial capacity is negative.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   243
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   244
    public HashMap(int initialCapacity) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   245
        this(initialCapacity, DEFAULT_LOAD_FACTOR);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   246
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   247
90ce3da70b43 Initial load
duke
parents:
diff changeset
   248
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   249
     * Constructs an empty <tt>HashMap</tt> with the default initial capacity
90ce3da70b43 Initial load
duke
parents:
diff changeset
   250
     * (16) and the default load factor (0.75).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   251
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   252
    public HashMap() {
12859
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   253
        this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   254
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   255
90ce3da70b43 Initial load
duke
parents:
diff changeset
   256
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   257
     * Constructs a new <tt>HashMap</tt> with the same mappings as the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   258
     * specified <tt>Map</tt>.  The <tt>HashMap</tt> is created with
90ce3da70b43 Initial load
duke
parents:
diff changeset
   259
     * default load factor (0.75) and an initial capacity sufficient to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   260
     * hold the mappings in the specified <tt>Map</tt>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   261
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   262
     * @param   m the map whose mappings are to be placed in this map
90ce3da70b43 Initial load
duke
parents:
diff changeset
   263
     * @throws  NullPointerException if the specified map is null
90ce3da70b43 Initial load
duke
parents:
diff changeset
   264
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   265
    public HashMap(Map<? extends K, ? extends V> m) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   266
        this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   267
                      DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   268
        putAllForCreate(m);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   269
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   270
90ce3da70b43 Initial load
duke
parents:
diff changeset
   271
    // internal utilities
90ce3da70b43 Initial load
duke
parents:
diff changeset
   272
90ce3da70b43 Initial load
duke
parents:
diff changeset
   273
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   274
     * Initialization hook for subclasses. This method is called
90ce3da70b43 Initial load
duke
parents:
diff changeset
   275
     * in all constructors and pseudo-constructors (clone, readObject)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   276
     * after HashMap has been initialized but before any entries have
90ce3da70b43 Initial load
duke
parents:
diff changeset
   277
     * been inserted.  (In the absence of this method, readObject would
90ce3da70b43 Initial load
duke
parents:
diff changeset
   278
     * require explicit knowledge of subclasses.)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   279
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   280
    void init() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   281
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   282
90ce3da70b43 Initial load
duke
parents:
diff changeset
   283
    /**
12859
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   284
     * Retrieve object hash code and applies a supplemental hash function to the
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   285
     * result hash, which defends against poor quality hash functions.  This is
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   286
     * critical because HashMap uses power-of-two length hash tables, that
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   287
     * otherwise encounter collisions for hashCodes that do not differ
12859
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   288
     * in lower bits.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   289
     */
12859
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   290
    final int hash(Object k) {
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   291
        int h = hashSeed;
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   292
        if (k instanceof String) {
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   293
            return ((String)k).hash32();
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   294
        }
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   295
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   296
        h ^= k.hashCode();
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   297
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   298
        // This function ensures that hashCodes that differ only by
90ce3da70b43 Initial load
duke
parents:
diff changeset
   299
        // constant multiples at each bit position have a bounded
90ce3da70b43 Initial load
duke
parents:
diff changeset
   300
        // number of collisions (approximately 8 at default load factor).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   301
        h ^= (h >>> 20) ^ (h >>> 12);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   302
        return h ^ (h >>> 7) ^ (h >>> 4);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   303
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   304
90ce3da70b43 Initial load
duke
parents:
diff changeset
   305
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   306
     * Returns index for hash code h.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   307
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   308
    static int indexFor(int h, int length) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   309
        return h & (length-1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   310
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   311
90ce3da70b43 Initial load
duke
parents:
diff changeset
   312
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   313
     * Returns the number of key-value mappings in this map.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   314
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   315
     * @return the number of key-value mappings in this map
90ce3da70b43 Initial load
duke
parents:
diff changeset
   316
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   317
    public int size() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   318
        return size;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   319
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   320
90ce3da70b43 Initial load
duke
parents:
diff changeset
   321
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   322
     * Returns <tt>true</tt> if this map contains no key-value mappings.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   323
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   324
     * @return <tt>true</tt> if this map contains no key-value mappings
90ce3da70b43 Initial load
duke
parents:
diff changeset
   325
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   326
    public boolean isEmpty() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   327
        return size == 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   328
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   329
90ce3da70b43 Initial load
duke
parents:
diff changeset
   330
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   331
     * Returns the value to which the specified key is mapped,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   332
     * or {@code null} if this map contains no mapping for the key.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   333
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   334
     * <p>More formally, if this map contains a mapping from a key
90ce3da70b43 Initial load
duke
parents:
diff changeset
   335
     * {@code k} to a value {@code v} such that {@code (key==null ? k==null :
90ce3da70b43 Initial load
duke
parents:
diff changeset
   336
     * key.equals(k))}, then this method returns {@code v}; otherwise
90ce3da70b43 Initial load
duke
parents:
diff changeset
   337
     * it returns {@code null}.  (There can be at most one such mapping.)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   338
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   339
     * <p>A return value of {@code null} does not <i>necessarily</i>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   340
     * indicate that the map contains no mapping for the key; it's also
90ce3da70b43 Initial load
duke
parents:
diff changeset
   341
     * possible that the map explicitly maps the key to {@code null}.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   342
     * The {@link #containsKey containsKey} operation may be used to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   343
     * distinguish these two cases.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   344
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   345
     * @see #put(Object, Object)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   346
     */
12448
b95438b17098 7157893: Warnings Cleanup in java.util.*
khazra
parents: 9035
diff changeset
   347
    @SuppressWarnings("unchecked")
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   348
    public V get(Object key) {
12859
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   349
        Entry<K,V> entry = getEntry(key);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   350
12859
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   351
        return null == entry ? null : entry.getValue();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   352
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   353
90ce3da70b43 Initial load
duke
parents:
diff changeset
   354
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   355
     * Returns <tt>true</tt> if this map contains a mapping for the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   356
     * specified key.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   357
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   358
     * @param   key   The key whose presence in this map is to be tested
90ce3da70b43 Initial load
duke
parents:
diff changeset
   359
     * @return <tt>true</tt> if this map contains a mapping for the specified
90ce3da70b43 Initial load
duke
parents:
diff changeset
   360
     * key.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   361
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   362
    public boolean containsKey(Object key) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   363
        return getEntry(key) != null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   364
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   365
90ce3da70b43 Initial load
duke
parents:
diff changeset
   366
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   367
     * Returns the entry associated with the specified key in the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   368
     * HashMap.  Returns null if the HashMap contains no mapping
90ce3da70b43 Initial load
duke
parents:
diff changeset
   369
     * for the key.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   370
     */
12448
b95438b17098 7157893: Warnings Cleanup in java.util.*
khazra
parents: 9035
diff changeset
   371
    @SuppressWarnings("unchecked")
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   372
    final Entry<K,V> getEntry(Object key) {
12859
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   373
        int hash = (key == null) ? 0 : hash(key);
12448
b95438b17098 7157893: Warnings Cleanup in java.util.*
khazra
parents: 9035
diff changeset
   374
        for (Entry<?,?> e = table[indexFor(hash, table.length)];
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   375
             e != null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   376
             e = e.next) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   377
            Object k;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   378
            if (e.hash == hash &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   379
                ((k = e.key) == key || (key != null && key.equals(k))))
12448
b95438b17098 7157893: Warnings Cleanup in java.util.*
khazra
parents: 9035
diff changeset
   380
                return (Entry<K,V>)e;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   381
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   382
        return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   383
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   384
90ce3da70b43 Initial load
duke
parents:
diff changeset
   385
90ce3da70b43 Initial load
duke
parents:
diff changeset
   386
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   387
     * Associates the specified value with the specified key in this map.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   388
     * If the map previously contained a mapping for the key, the old
90ce3da70b43 Initial load
duke
parents:
diff changeset
   389
     * value is replaced.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   390
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   391
     * @param key key with which the specified value is to be associated
90ce3da70b43 Initial load
duke
parents:
diff changeset
   392
     * @param value value to be associated with the specified key
90ce3da70b43 Initial load
duke
parents:
diff changeset
   393
     * @return the previous value associated with <tt>key</tt>, or
90ce3da70b43 Initial load
duke
parents:
diff changeset
   394
     *         <tt>null</tt> if there was no mapping for <tt>key</tt>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   395
     *         (A <tt>null</tt> return can also indicate that the map
90ce3da70b43 Initial load
duke
parents:
diff changeset
   396
     *         previously associated <tt>null</tt> with <tt>key</tt>.)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   397
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   398
    public V put(K key, V value) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   399
        if (key == null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   400
            return putForNullKey(value);
12859
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   401
        int hash = hash(key);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   402
        int i = indexFor(hash, table.length);
12448
b95438b17098 7157893: Warnings Cleanup in java.util.*
khazra
parents: 9035
diff changeset
   403
        @SuppressWarnings("unchecked")
b95438b17098 7157893: Warnings Cleanup in java.util.*
khazra
parents: 9035
diff changeset
   404
        Entry<K,V> e = (Entry<K,V>)table[i];
b95438b17098 7157893: Warnings Cleanup in java.util.*
khazra
parents: 9035
diff changeset
   405
        for(; e != null; e = e.next) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   406
            Object k;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   407
            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   408
                V oldValue = e.value;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   409
                e.value = value;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   410
                e.recordAccess(this);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   411
                return oldValue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   412
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   413
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   414
90ce3da70b43 Initial load
duke
parents:
diff changeset
   415
        modCount++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   416
        addEntry(hash, key, value, i);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   417
        return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   418
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   419
90ce3da70b43 Initial load
duke
parents:
diff changeset
   420
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   421
     * Offloaded version of put for null keys
90ce3da70b43 Initial load
duke
parents:
diff changeset
   422
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   423
    private V putForNullKey(V value) {
12448
b95438b17098 7157893: Warnings Cleanup in java.util.*
khazra
parents: 9035
diff changeset
   424
        @SuppressWarnings("unchecked")
b95438b17098 7157893: Warnings Cleanup in java.util.*
khazra
parents: 9035
diff changeset
   425
        Entry<K,V> e = (Entry<K,V>)table[0];
b95438b17098 7157893: Warnings Cleanup in java.util.*
khazra
parents: 9035
diff changeset
   426
        for(; e != null; e = e.next) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   427
            if (e.key == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   428
                V oldValue = e.value;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   429
                e.value = value;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   430
                e.recordAccess(this);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   431
                return oldValue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   432
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   433
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   434
        modCount++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   435
        addEntry(0, null, value, 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   436
        return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   437
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   438
90ce3da70b43 Initial load
duke
parents:
diff changeset
   439
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   440
     * This method is used instead of put by constructors and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   441
     * pseudoconstructors (clone, readObject).  It does not resize the table,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   442
     * check for comodification, etc.  It calls createEntry rather than
90ce3da70b43 Initial load
duke
parents:
diff changeset
   443
     * addEntry.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   444
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   445
    private void putForCreate(K key, V value) {
12859
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   446
        int hash = null == key ? 0 : hash(key);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   447
        int i = indexFor(hash, table.length);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   448
90ce3da70b43 Initial load
duke
parents:
diff changeset
   449
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   450
         * Look for preexisting entry for key.  This will never happen for
90ce3da70b43 Initial load
duke
parents:
diff changeset
   451
         * clone or deserialize.  It will only happen for construction if the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   452
         * input Map is a sorted map whose ordering is inconsistent w/ equals.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   453
         */
12448
b95438b17098 7157893: Warnings Cleanup in java.util.*
khazra
parents: 9035
diff changeset
   454
        for (@SuppressWarnings("unchecked")
b95438b17098 7157893: Warnings Cleanup in java.util.*
khazra
parents: 9035
diff changeset
   455
             Entry<?,V> e = (Entry<?,V>)table[i]; e != null; e = e.next) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   456
            Object k;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   457
            if (e.hash == hash &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   458
                ((k = e.key) == key || (key != null && key.equals(k)))) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   459
                e.value = value;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   460
                return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   461
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   462
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   463
90ce3da70b43 Initial load
duke
parents:
diff changeset
   464
        createEntry(hash, key, value, i);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   465
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   466
90ce3da70b43 Initial load
duke
parents:
diff changeset
   467
    private void putAllForCreate(Map<? extends K, ? extends V> m) {
4110
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents: 715
diff changeset
   468
        for (Map.Entry<? extends K, ? extends V> e : m.entrySet())
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   469
            putForCreate(e.getKey(), e.getValue());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   470
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   471
90ce3da70b43 Initial load
duke
parents:
diff changeset
   472
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   473
     * Rehashes the contents of this map into a new array with a
90ce3da70b43 Initial load
duke
parents:
diff changeset
   474
     * larger capacity.  This method is called automatically when the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   475
     * number of keys in this map reaches its threshold.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   476
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   477
     * If current capacity is MAXIMUM_CAPACITY, this method does not
90ce3da70b43 Initial load
duke
parents:
diff changeset
   478
     * resize the map, but sets threshold to Integer.MAX_VALUE.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   479
     * This has the effect of preventing future calls.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   480
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   481
     * @param newCapacity the new capacity, MUST be a power of two;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   482
     *        must be greater than current capacity unless current
90ce3da70b43 Initial load
duke
parents:
diff changeset
   483
     *        capacity is MAXIMUM_CAPACITY (in which case value
90ce3da70b43 Initial load
duke
parents:
diff changeset
   484
     *        is irrelevant).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   485
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   486
    void resize(int newCapacity) {
12448
b95438b17098 7157893: Warnings Cleanup in java.util.*
khazra
parents: 9035
diff changeset
   487
        Entry<?,?>[] oldTable = table;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   488
        int oldCapacity = oldTable.length;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   489
        if (oldCapacity == MAXIMUM_CAPACITY) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   490
            threshold = Integer.MAX_VALUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   491
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   492
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   493
12448
b95438b17098 7157893: Warnings Cleanup in java.util.*
khazra
parents: 9035
diff changeset
   494
        Entry<?,?>[] newTable = new Entry<?,?>[newCapacity];
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   495
        transfer(newTable);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   496
        table = newTable;
12859
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   497
        threshold = (int)Math.min(newCapacity * loadFactor, MAXIMUM_CAPACITY + 1);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   498
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   499
90ce3da70b43 Initial load
duke
parents:
diff changeset
   500
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   501
     * Transfers all entries from current table to newTable.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   502
     */
12448
b95438b17098 7157893: Warnings Cleanup in java.util.*
khazra
parents: 9035
diff changeset
   503
    @SuppressWarnings("unchecked")
b95438b17098 7157893: Warnings Cleanup in java.util.*
khazra
parents: 9035
diff changeset
   504
    void transfer(Entry<?,?>[] newTable) {
b95438b17098 7157893: Warnings Cleanup in java.util.*
khazra
parents: 9035
diff changeset
   505
        Entry<?,?>[] src = table;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   506
        int newCapacity = newTable.length;
12859
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   507
        for (int j = 0; j < src.length; j++ ) {
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   508
            Entry<K,V> e = (Entry<K,V>) src[j];
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   509
            while(null != e) {
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   510
                Entry<K,V> next = e.next;
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   511
                int i = indexFor(e.hash, newCapacity);
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   512
                e.next = (Entry<K,V>) newTable[i];
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   513
                newTable[i] = e;
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   514
                e = next;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   515
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   516
        }
12859
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   517
        Arrays.fill(table, null);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   518
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   519
90ce3da70b43 Initial load
duke
parents:
diff changeset
   520
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   521
     * Copies all of the mappings from the specified map to this map.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   522
     * These mappings will replace any mappings that this map had for
90ce3da70b43 Initial load
duke
parents:
diff changeset
   523
     * any of the keys currently in the specified map.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   524
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   525
     * @param m mappings to be stored in this map
90ce3da70b43 Initial load
duke
parents:
diff changeset
   526
     * @throws NullPointerException if the specified map is null
90ce3da70b43 Initial load
duke
parents:
diff changeset
   527
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   528
    public void putAll(Map<? extends K, ? extends V> m) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   529
        int numKeysToBeAdded = m.size();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   530
        if (numKeysToBeAdded == 0)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   531
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   532
90ce3da70b43 Initial load
duke
parents:
diff changeset
   533
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   534
         * Expand the map if the map if the number of mappings to be added
90ce3da70b43 Initial load
duke
parents:
diff changeset
   535
         * is greater than or equal to threshold.  This is conservative; the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   536
         * obvious condition is (m.size() + size) >= threshold, but this
90ce3da70b43 Initial load
duke
parents:
diff changeset
   537
         * condition could result in a map with twice the appropriate capacity,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   538
         * if the keys to be added overlap with the keys already in this map.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   539
         * By using the conservative calculation, we subject ourself
90ce3da70b43 Initial load
duke
parents:
diff changeset
   540
         * to at most one extra resize.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   541
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   542
        if (numKeysToBeAdded > threshold) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   543
            int targetCapacity = (int)(numKeysToBeAdded / loadFactor + 1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   544
            if (targetCapacity > MAXIMUM_CAPACITY)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   545
                targetCapacity = MAXIMUM_CAPACITY;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   546
            int newCapacity = table.length;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   547
            while (newCapacity < targetCapacity)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   548
                newCapacity <<= 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   549
            if (newCapacity > table.length)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   550
                resize(newCapacity);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   551
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   552
4110
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents: 715
diff changeset
   553
        for (Map.Entry<? extends K, ? extends V> e : m.entrySet())
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   554
            put(e.getKey(), e.getValue());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   555
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   556
90ce3da70b43 Initial load
duke
parents:
diff changeset
   557
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   558
     * Removes the mapping for the specified key from this map if present.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   559
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   560
     * @param  key key whose mapping is to be removed from the map
90ce3da70b43 Initial load
duke
parents:
diff changeset
   561
     * @return the previous value associated with <tt>key</tt>, or
90ce3da70b43 Initial load
duke
parents:
diff changeset
   562
     *         <tt>null</tt> if there was no mapping for <tt>key</tt>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   563
     *         (A <tt>null</tt> return can also indicate that the map
90ce3da70b43 Initial load
duke
parents:
diff changeset
   564
     *         previously associated <tt>null</tt> with <tt>key</tt>.)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   565
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   566
    public V remove(Object key) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   567
        Entry<K,V> e = removeEntryForKey(key);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   568
        return (e == null ? null : e.value);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   569
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   570
90ce3da70b43 Initial load
duke
parents:
diff changeset
   571
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   572
     * Removes and returns the entry associated with the specified key
90ce3da70b43 Initial load
duke
parents:
diff changeset
   573
     * in the HashMap.  Returns null if the HashMap contains no mapping
90ce3da70b43 Initial load
duke
parents:
diff changeset
   574
     * for this key.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   575
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   576
    final Entry<K,V> removeEntryForKey(Object key) {
12859
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   577
        int hash = (key == null) ? 0 : hash(key);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   578
        int i = indexFor(hash, table.length);
12448
b95438b17098 7157893: Warnings Cleanup in java.util.*
khazra
parents: 9035
diff changeset
   579
        @SuppressWarnings("unchecked")
b95438b17098 7157893: Warnings Cleanup in java.util.*
khazra
parents: 9035
diff changeset
   580
            Entry<K,V> prev = (Entry<K,V>)table[i];
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   581
        Entry<K,V> e = prev;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   582
90ce3da70b43 Initial load
duke
parents:
diff changeset
   583
        while (e != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   584
            Entry<K,V> next = e.next;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   585
            Object k;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   586
            if (e.hash == hash &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   587
                ((k = e.key) == key || (key != null && key.equals(k)))) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   588
                modCount++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   589
                size--;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   590
                if (prev == e)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   591
                    table[i] = next;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   592
                else
90ce3da70b43 Initial load
duke
parents:
diff changeset
   593
                    prev.next = next;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   594
                e.recordRemoval(this);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   595
                return e;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   596
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   597
            prev = e;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   598
            e = next;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   599
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   600
90ce3da70b43 Initial load
duke
parents:
diff changeset
   601
        return e;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   602
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   603
90ce3da70b43 Initial load
duke
parents:
diff changeset
   604
    /**
12859
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   605
     * Special version of remove for EntrySet using {@code Map.Entry.equals()}
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   606
     * for matching.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   607
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   608
    final Entry<K,V> removeMapping(Object o) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   609
        if (!(o instanceof Map.Entry))
90ce3da70b43 Initial load
duke
parents:
diff changeset
   610
            return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   611
12448
b95438b17098 7157893: Warnings Cleanup in java.util.*
khazra
parents: 9035
diff changeset
   612
        Map.Entry<?,?> entry = (Map.Entry<?,?>) o;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   613
        Object key = entry.getKey();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   614
        int hash = (key == null) ? 0 : hash(key.hashCode());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   615
        int i = indexFor(hash, table.length);
12448
b95438b17098 7157893: Warnings Cleanup in java.util.*
khazra
parents: 9035
diff changeset
   616
        @SuppressWarnings("unchecked")
b95438b17098 7157893: Warnings Cleanup in java.util.*
khazra
parents: 9035
diff changeset
   617
            Entry<K,V> prev = (Entry<K,V>)table[i];
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   618
        Entry<K,V> e = prev;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   619
90ce3da70b43 Initial load
duke
parents:
diff changeset
   620
        while (e != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   621
            Entry<K,V> next = e.next;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   622
            if (e.hash == hash && e.equals(entry)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   623
                modCount++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   624
                size--;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   625
                if (prev == e)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   626
                    table[i] = next;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   627
                else
90ce3da70b43 Initial load
duke
parents:
diff changeset
   628
                    prev.next = next;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   629
                e.recordRemoval(this);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   630
                return e;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   631
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   632
            prev = e;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   633
            e = next;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   634
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   635
90ce3da70b43 Initial load
duke
parents:
diff changeset
   636
        return e;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   637
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   638
90ce3da70b43 Initial load
duke
parents:
diff changeset
   639
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   640
     * Removes all of the mappings from this map.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   641
     * The map will be empty after this call returns.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   642
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   643
    public void clear() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   644
        modCount++;
12448
b95438b17098 7157893: Warnings Cleanup in java.util.*
khazra
parents: 9035
diff changeset
   645
        Entry<?,?>[] tab = table;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   646
        for (int i = 0; i < tab.length; i++)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   647
            tab[i] = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   648
        size = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   649
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   650
90ce3da70b43 Initial load
duke
parents:
diff changeset
   651
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   652
     * Returns <tt>true</tt> if this map maps one or more keys to the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   653
     * specified value.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   654
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   655
     * @param value value whose presence in this map is to be tested
90ce3da70b43 Initial load
duke
parents:
diff changeset
   656
     * @return <tt>true</tt> if this map maps one or more keys to the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   657
     *         specified value
90ce3da70b43 Initial load
duke
parents:
diff changeset
   658
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   659
    public boolean containsValue(Object value) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   660
        if (value == null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   661
            return containsNullValue();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   662
12448
b95438b17098 7157893: Warnings Cleanup in java.util.*
khazra
parents: 9035
diff changeset
   663
        Entry<?,?>[] tab = table;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   664
        for (int i = 0; i < tab.length ; i++)
12448
b95438b17098 7157893: Warnings Cleanup in java.util.*
khazra
parents: 9035
diff changeset
   665
            for (Entry<?,?> e = tab[i] ; e != null ; e = e.next)
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   666
                if (value.equals(e.value))
90ce3da70b43 Initial load
duke
parents:
diff changeset
   667
                    return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   668
        return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   669
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   670
90ce3da70b43 Initial load
duke
parents:
diff changeset
   671
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   672
     * Special-case code for containsValue with null argument
90ce3da70b43 Initial load
duke
parents:
diff changeset
   673
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   674
    private boolean containsNullValue() {
12448
b95438b17098 7157893: Warnings Cleanup in java.util.*
khazra
parents: 9035
diff changeset
   675
        Entry<?,?>[] tab = table;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   676
        for (int i = 0; i < tab.length ; i++)
12448
b95438b17098 7157893: Warnings Cleanup in java.util.*
khazra
parents: 9035
diff changeset
   677
            for (Entry<?,?> e = tab[i] ; e != null ; e = e.next)
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   678
                if (e.value == null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   679
                    return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   680
        return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   681
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   682
90ce3da70b43 Initial load
duke
parents:
diff changeset
   683
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   684
     * Returns a shallow copy of this <tt>HashMap</tt> instance: the keys and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   685
     * values themselves are not cloned.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   686
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   687
     * @return a shallow copy of this map
90ce3da70b43 Initial load
duke
parents:
diff changeset
   688
     */
12448
b95438b17098 7157893: Warnings Cleanup in java.util.*
khazra
parents: 9035
diff changeset
   689
    @SuppressWarnings("unchecked")
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   690
    public Object clone() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   691
        HashMap<K,V> result = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   692
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   693
            result = (HashMap<K,V>)super.clone();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   694
        } catch (CloneNotSupportedException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   695
            // assert false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   696
        }
12448
b95438b17098 7157893: Warnings Cleanup in java.util.*
khazra
parents: 9035
diff changeset
   697
        result.table = new Entry<?,?>[table.length];
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   698
        result.entrySet = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   699
        result.modCount = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   700
        result.size = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   701
        result.init();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   702
        result.putAllForCreate(this);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   703
90ce3da70b43 Initial load
duke
parents:
diff changeset
   704
        return result;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   705
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   706
90ce3da70b43 Initial load
duke
parents:
diff changeset
   707
    static class Entry<K,V> implements Map.Entry<K,V> {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   708
        final K key;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   709
        V value;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   710
        Entry<K,V> next;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   711
        final int hash;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   712
90ce3da70b43 Initial load
duke
parents:
diff changeset
   713
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   714
         * Creates new entry.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   715
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   716
        Entry(int h, K k, V v, Entry<K,V> n) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   717
            value = v;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   718
            next = n;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   719
            key = k;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   720
            hash = h;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   721
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   722
90ce3da70b43 Initial load
duke
parents:
diff changeset
   723
        public final K getKey() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   724
            return key;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   725
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   726
90ce3da70b43 Initial load
duke
parents:
diff changeset
   727
        public final V getValue() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   728
            return value;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   729
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   730
90ce3da70b43 Initial load
duke
parents:
diff changeset
   731
        public final V setValue(V newValue) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   732
            V oldValue = value;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   733
            value = newValue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   734
            return oldValue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   735
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   736
90ce3da70b43 Initial load
duke
parents:
diff changeset
   737
        public final boolean equals(Object o) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   738
            if (!(o instanceof Map.Entry))
90ce3da70b43 Initial load
duke
parents:
diff changeset
   739
                return false;
12448
b95438b17098 7157893: Warnings Cleanup in java.util.*
khazra
parents: 9035
diff changeset
   740
            Map.Entry<?,?> e = (Map.Entry<?,?>)o;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   741
            Object k1 = getKey();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   742
            Object k2 = e.getKey();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   743
            if (k1 == k2 || (k1 != null && k1.equals(k2))) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   744
                Object v1 = getValue();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   745
                Object v2 = e.getValue();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   746
                if (v1 == v2 || (v1 != null && v1.equals(v2)))
90ce3da70b43 Initial load
duke
parents:
diff changeset
   747
                    return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   748
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   749
            return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   750
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   751
90ce3da70b43 Initial load
duke
parents:
diff changeset
   752
        public final int hashCode() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   753
            return (key==null   ? 0 : key.hashCode()) ^
90ce3da70b43 Initial load
duke
parents:
diff changeset
   754
                   (value==null ? 0 : value.hashCode());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   755
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   756
90ce3da70b43 Initial load
duke
parents:
diff changeset
   757
        public final String toString() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   758
            return getKey() + "=" + getValue();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   759
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   760
90ce3da70b43 Initial load
duke
parents:
diff changeset
   761
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   762
         * This method is invoked whenever the value in an entry is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   763
         * overwritten by an invocation of put(k,v) for a key k that's already
90ce3da70b43 Initial load
duke
parents:
diff changeset
   764
         * in the HashMap.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   765
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   766
        void recordAccess(HashMap<K,V> m) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   767
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   768
90ce3da70b43 Initial load
duke
parents:
diff changeset
   769
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   770
         * This method is invoked whenever the entry is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   771
         * removed from the table.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   772
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   773
        void recordRemoval(HashMap<K,V> m) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   774
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   775
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   776
90ce3da70b43 Initial load
duke
parents:
diff changeset
   777
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   778
     * Adds a new entry with the specified key, value and hash code to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   779
     * the specified bucket.  It is the responsibility of this
90ce3da70b43 Initial load
duke
parents:
diff changeset
   780
     * method to resize the table if appropriate.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   781
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   782
     * Subclass overrides this to alter the behavior of put method.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   783
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   784
    void addEntry(int hash, K key, V value, int bucketIndex) {
12859
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   785
        if ((size >= threshold) && (null != table[bucketIndex])) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   786
            resize(2 * table.length);
12859
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   787
            hash = hash(key);
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   788
            bucketIndex = indexFor(hash, table.length);
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   789
        }
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   790
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
   791
        createEntry(hash, key, value, bucketIndex);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   792
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   793
90ce3da70b43 Initial load
duke
parents:
diff changeset
   794
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   795
     * Like addEntry except that this version is used when creating entries
90ce3da70b43 Initial load
duke
parents:
diff changeset
   796
     * as part of Map construction or "pseudo-construction" (cloning,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   797
     * deserialization).  This version needn't worry about resizing the table.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   798
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   799
     * Subclass overrides this to alter the behavior of HashMap(Map),
90ce3da70b43 Initial load
duke
parents:
diff changeset
   800
     * clone, and readObject.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   801
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   802
    void createEntry(int hash, K key, V value, int bucketIndex) {
12448
b95438b17098 7157893: Warnings Cleanup in java.util.*
khazra
parents: 9035
diff changeset
   803
        @SuppressWarnings("unchecked")
b95438b17098 7157893: Warnings Cleanup in java.util.*
khazra
parents: 9035
diff changeset
   804
            Entry<K,V> e = (Entry<K,V>)table[bucketIndex];
7803
56bc97d69d93 6880112: Project Coin: Port JDK core library code to use diamond operator
smarks
parents: 5506
diff changeset
   805
        table[bucketIndex] = new Entry<>(hash, key, value, e);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   806
        size++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   807
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   808
90ce3da70b43 Initial load
duke
parents:
diff changeset
   809
    private abstract class HashIterator<E> implements Iterator<E> {
12448
b95438b17098 7157893: Warnings Cleanup in java.util.*
khazra
parents: 9035
diff changeset
   810
        Entry<?,?> next;        // next entry to return
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   811
        int expectedModCount;   // For fast-fail
90ce3da70b43 Initial load
duke
parents:
diff changeset
   812
        int index;              // current slot
12448
b95438b17098 7157893: Warnings Cleanup in java.util.*
khazra
parents: 9035
diff changeset
   813
        Entry<?,?> current;     // current entry
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   814
90ce3da70b43 Initial load
duke
parents:
diff changeset
   815
        HashIterator() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   816
            expectedModCount = modCount;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   817
            if (size > 0) { // advance to first entry
12448
b95438b17098 7157893: Warnings Cleanup in java.util.*
khazra
parents: 9035
diff changeset
   818
                Entry<?,?>[] t = table;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   819
                while (index < t.length && (next = t[index++]) == null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   820
                    ;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   821
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   822
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   823
90ce3da70b43 Initial load
duke
parents:
diff changeset
   824
        public final boolean hasNext() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   825
            return next != null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   826
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   827
12448
b95438b17098 7157893: Warnings Cleanup in java.util.*
khazra
parents: 9035
diff changeset
   828
        @SuppressWarnings("unchecked")
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   829
        final Entry<K,V> nextEntry() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   830
            if (modCount != expectedModCount)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   831
                throw new ConcurrentModificationException();
12448
b95438b17098 7157893: Warnings Cleanup in java.util.*
khazra
parents: 9035
diff changeset
   832
            Entry<?,?> e = next;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   833
            if (e == null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   834
                throw new NoSuchElementException();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   835
90ce3da70b43 Initial load
duke
parents:
diff changeset
   836
            if ((next = e.next) == null) {
12448
b95438b17098 7157893: Warnings Cleanup in java.util.*
khazra
parents: 9035
diff changeset
   837
                Entry<?,?>[] t = table;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   838
                while (index < t.length && (next = t[index++]) == null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   839
                    ;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   840
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   841
            current = e;
12448
b95438b17098 7157893: Warnings Cleanup in java.util.*
khazra
parents: 9035
diff changeset
   842
            return (Entry<K,V>)e;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   843
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   844
90ce3da70b43 Initial load
duke
parents:
diff changeset
   845
        public void remove() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   846
            if (current == null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   847
                throw new IllegalStateException();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   848
            if (modCount != expectedModCount)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   849
                throw new ConcurrentModificationException();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   850
            Object k = current.key;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   851
            current = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   852
            HashMap.this.removeEntryForKey(k);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   853
            expectedModCount = modCount;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   854
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   855
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   856
90ce3da70b43 Initial load
duke
parents:
diff changeset
   857
    private final class ValueIterator extends HashIterator<V> {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   858
        public V next() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   859
            return nextEntry().value;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   860
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   861
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   862
90ce3da70b43 Initial load
duke
parents:
diff changeset
   863
    private final class KeyIterator extends HashIterator<K> {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   864
        public K next() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   865
            return nextEntry().getKey();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   866
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   867
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   868
90ce3da70b43 Initial load
duke
parents:
diff changeset
   869
    private final class EntryIterator extends HashIterator<Map.Entry<K,V>> {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   870
        public Map.Entry<K,V> next() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   871
            return nextEntry();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   872
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   873
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   874
90ce3da70b43 Initial load
duke
parents:
diff changeset
   875
    // Subclass overrides these to alter behavior of views' iterator() method
90ce3da70b43 Initial load
duke
parents:
diff changeset
   876
    Iterator<K> newKeyIterator()   {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   877
        return new KeyIterator();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   878
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   879
    Iterator<V> newValueIterator()   {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   880
        return new ValueIterator();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   881
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   882
    Iterator<Map.Entry<K,V>> newEntryIterator()   {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   883
        return new EntryIterator();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   884
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   885
90ce3da70b43 Initial load
duke
parents:
diff changeset
   886
90ce3da70b43 Initial load
duke
parents:
diff changeset
   887
    // Views
90ce3da70b43 Initial load
duke
parents:
diff changeset
   888
90ce3da70b43 Initial load
duke
parents:
diff changeset
   889
    private transient Set<Map.Entry<K,V>> entrySet = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   890
90ce3da70b43 Initial load
duke
parents:
diff changeset
   891
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   892
     * Returns a {@link Set} view of the keys contained in this map.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   893
     * The set is backed by the map, so changes to the map are
90ce3da70b43 Initial load
duke
parents:
diff changeset
   894
     * reflected in the set, and vice-versa.  If the map is modified
90ce3da70b43 Initial load
duke
parents:
diff changeset
   895
     * while an iteration over the set is in progress (except through
90ce3da70b43 Initial load
duke
parents:
diff changeset
   896
     * the iterator's own <tt>remove</tt> operation), the results of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   897
     * the iteration are undefined.  The set supports element removal,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   898
     * which removes the corresponding mapping from the map, via the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   899
     * <tt>Iterator.remove</tt>, <tt>Set.remove</tt>,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   900
     * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   901
     * operations.  It does not support the <tt>add</tt> or <tt>addAll</tt>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   902
     * operations.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   903
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   904
    public Set<K> keySet() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   905
        Set<K> ks = keySet;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   906
        return (ks != null ? ks : (keySet = new KeySet()));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   907
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   908
90ce3da70b43 Initial load
duke
parents:
diff changeset
   909
    private final class KeySet extends AbstractSet<K> {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   910
        public Iterator<K> iterator() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   911
            return newKeyIterator();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   912
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   913
        public int size() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   914
            return size;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   915
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   916
        public boolean contains(Object o) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   917
            return containsKey(o);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   918
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   919
        public boolean remove(Object o) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   920
            return HashMap.this.removeEntryForKey(o) != null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   921
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   922
        public void clear() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   923
            HashMap.this.clear();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   924
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   925
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   926
90ce3da70b43 Initial load
duke
parents:
diff changeset
   927
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   928
     * Returns a {@link Collection} view of the values contained in this map.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   929
     * The collection is backed by the map, so changes to the map are
90ce3da70b43 Initial load
duke
parents:
diff changeset
   930
     * reflected in the collection, and vice-versa.  If the map is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   931
     * modified while an iteration over the collection is in progress
90ce3da70b43 Initial load
duke
parents:
diff changeset
   932
     * (except through the iterator's own <tt>remove</tt> operation),
90ce3da70b43 Initial load
duke
parents:
diff changeset
   933
     * the results of the iteration are undefined.  The collection
90ce3da70b43 Initial load
duke
parents:
diff changeset
   934
     * supports element removal, which removes the corresponding
90ce3da70b43 Initial load
duke
parents:
diff changeset
   935
     * mapping from the map, via the <tt>Iterator.remove</tt>,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   936
     * <tt>Collection.remove</tt>, <tt>removeAll</tt>,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   937
     * <tt>retainAll</tt> and <tt>clear</tt> operations.  It does not
90ce3da70b43 Initial load
duke
parents:
diff changeset
   938
     * support the <tt>add</tt> or <tt>addAll</tt> operations.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   939
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   940
    public Collection<V> values() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   941
        Collection<V> vs = values;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   942
        return (vs != null ? vs : (values = new Values()));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   943
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   944
90ce3da70b43 Initial load
duke
parents:
diff changeset
   945
    private final class Values extends AbstractCollection<V> {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   946
        public Iterator<V> iterator() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   947
            return newValueIterator();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   948
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   949
        public int size() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   950
            return size;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   951
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   952
        public boolean contains(Object o) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   953
            return containsValue(o);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   954
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   955
        public void clear() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   956
            HashMap.this.clear();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   957
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   958
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   959
90ce3da70b43 Initial load
duke
parents:
diff changeset
   960
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   961
     * Returns a {@link Set} view of the mappings contained in this map.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   962
     * The set is backed by the map, so changes to the map are
90ce3da70b43 Initial load
duke
parents:
diff changeset
   963
     * reflected in the set, and vice-versa.  If the map is modified
90ce3da70b43 Initial load
duke
parents:
diff changeset
   964
     * while an iteration over the set is in progress (except through
90ce3da70b43 Initial load
duke
parents:
diff changeset
   965
     * the iterator's own <tt>remove</tt> operation, or through the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   966
     * <tt>setValue</tt> operation on a map entry returned by the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   967
     * iterator) the results of the iteration are undefined.  The set
90ce3da70b43 Initial load
duke
parents:
diff changeset
   968
     * supports element removal, which removes the corresponding
90ce3da70b43 Initial load
duke
parents:
diff changeset
   969
     * mapping from the map, via the <tt>Iterator.remove</tt>,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   970
     * <tt>Set.remove</tt>, <tt>removeAll</tt>, <tt>retainAll</tt> and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   971
     * <tt>clear</tt> operations.  It does not support the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   972
     * <tt>add</tt> or <tt>addAll</tt> operations.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   973
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   974
     * @return a set view of the mappings contained in this map
90ce3da70b43 Initial load
duke
parents:
diff changeset
   975
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   976
    public Set<Map.Entry<K,V>> entrySet() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   977
        return entrySet0();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   978
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   979
90ce3da70b43 Initial load
duke
parents:
diff changeset
   980
    private Set<Map.Entry<K,V>> entrySet0() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   981
        Set<Map.Entry<K,V>> es = entrySet;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   982
        return es != null ? es : (entrySet = new EntrySet());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   983
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   984
90ce3da70b43 Initial load
duke
parents:
diff changeset
   985
    private final class EntrySet extends AbstractSet<Map.Entry<K,V>> {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   986
        public Iterator<Map.Entry<K,V>> iterator() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   987
            return newEntryIterator();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   988
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   989
        public boolean contains(Object o) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   990
            if (!(o instanceof Map.Entry))
90ce3da70b43 Initial load
duke
parents:
diff changeset
   991
                return false;
12448
b95438b17098 7157893: Warnings Cleanup in java.util.*
khazra
parents: 9035
diff changeset
   992
            Map.Entry<?,?> e = (Map.Entry<?,?>) o;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   993
            Entry<K,V> candidate = getEntry(e.getKey());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   994
            return candidate != null && candidate.equals(e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   995
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   996
        public boolean remove(Object o) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   997
            return removeMapping(o) != null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   998
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   999
        public int size() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1000
            return size;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1001
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1002
        public void clear() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1003
            HashMap.this.clear();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1004
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1005
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1006
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1007
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1008
     * Save the state of the <tt>HashMap</tt> instance to a stream (i.e.,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1009
     * serialize it).
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1010
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1011
     * @serialData The <i>capacity</i> of the HashMap (the length of the
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1012
     *             bucket array) is emitted (int), followed by the
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1013
     *             <i>size</i> (an int, the number of key-value
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1014
     *             mappings), followed by the key (Object) and value (Object)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1015
     *             for each key-value mapping.  The key-value mappings are
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1016
     *             emitted in no particular order.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1017
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1018
    private void writeObject(java.io.ObjectOutputStream s)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1019
        throws IOException
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1020
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1021
        Iterator<Map.Entry<K,V>> i =
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1022
            (size > 0) ? entrySet0().iterator() : null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1023
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1024
        // Write out the threshold, loadfactor, and any hidden stuff
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1025
        s.defaultWriteObject();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1026
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1027
        // Write out number of buckets
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1028
        s.writeInt(table.length);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1029
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1030
        // Write out size (number of Mappings)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1031
        s.writeInt(size);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1032
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1033
        // Write out keys and values (alternating)
12859
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
  1034
        if (size > 0) {
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
  1035
            for(Map.Entry<K,V> e : entrySet0()) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1036
                s.writeObject(e.getKey());
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1037
                s.writeObject(e.getValue());
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1038
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1039
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1040
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1041
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1042
    private static final long serialVersionUID = 362498820763181265L;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1043
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1044
    /**
12859
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
  1045
     * Reconstitute the {@code HashMap} instance from a stream (i.e.,
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1046
     * deserialize it).
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1047
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1048
    private void readObject(java.io.ObjectInputStream s)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1049
         throws IOException, ClassNotFoundException
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1050
    {
12859
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
  1051
        // Read in the threshold (ignored), loadfactor, and any hidden stuff
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1052
        s.defaultReadObject();
12859
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
  1053
        if (loadFactor <= 0 || Float.isNaN(loadFactor))
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
  1054
            throw new InvalidObjectException("Illegal load factor: " +
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
  1055
                                               loadFactor);
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
  1056
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
  1057
        // set hashMask
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
  1058
        Holder.UNSAFE.putIntVolatile(this, Holder.HASHSEED_OFFSET,
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
  1059
                sun.misc.Hashing.randomHashSeed(this));
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1060
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1061
        // Read in number of buckets and allocate the bucket array;
12859
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
  1062
        s.readInt(); // ignored
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
  1063
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
  1064
        // Read number of mappings
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
  1065
        int mappings = s.readInt();
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
  1066
        if (mappings < 0)
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
  1067
            throw new InvalidObjectException("Illegal mappings count: " +
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
  1068
                                               mappings);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1069
12859
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
  1070
        int initialCapacity = (int) Math.min(
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
  1071
                // capacity chosen by number of mappings
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
  1072
                // and desired load (if >= 0.25)
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
  1073
                mappings * Math.min(1 / loadFactor, 4.0f),
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
  1074
                // we have limits...
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
  1075
                HashMap.MAXIMUM_CAPACITY);
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
  1076
        int capacity = 1;
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
  1077
        // find smallest power of two which holds all mappings
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
  1078
        while (capacity < initialCapacity) {
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
  1079
            capacity <<= 1;
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
  1080
        }
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
  1081
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
  1082
        table = new Entry[capacity];
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
  1083
        threshold = (int) Math.min(capacity * loadFactor, MAXIMUM_CAPACITY + 1);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1084
        init();  // Give subclass a chance to do its thing.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1085
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1086
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1087
        // Read the keys and values, and put the mappings in the HashMap
12859
c44b88bb9b5e 7126277: Alternative String hashing implementation
mduigou
parents: 12448
diff changeset
  1088
        for (int i=0; i<mappings; i++) {
12448
b95438b17098 7157893: Warnings Cleanup in java.util.*
khazra
parents: 9035
diff changeset
  1089
            @SuppressWarnings("unchecked")
b95438b17098 7157893: Warnings Cleanup in java.util.*
khazra
parents: 9035
diff changeset
  1090
                K key = (K) s.readObject();
b95438b17098 7157893: Warnings Cleanup in java.util.*
khazra
parents: 9035
diff changeset
  1091
            @SuppressWarnings("unchecked")
b95438b17098 7157893: Warnings Cleanup in java.util.*
khazra
parents: 9035
diff changeset
  1092
                V value = (V) s.readObject();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1093
            putForCreate(key, value);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1094
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1095
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1096
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1097
    // These methods are used when serializing HashSets
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1098
    int   capacity()     { return table.length; }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1099
    float loadFactor()   { return loadFactor;   }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1100
}