java源码解析---HashMap

   1 /*
   2  *  %W% %E%
   3  *
   4  * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
   5  * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
   6  */
   7 package explain;
   8 import java.io.*;
   9 import java.util.AbstractCollection;
  10 import java.util.AbstractMap;
  11 import java.util.AbstractSet;
  12 import java.util.Collection;
  13 import java.util.ConcurrentModificationException;
  14 import java.util.Iterator;
  15 import java.util.Map;
  16 import java.util.NoSuchElementException;
  17 import java.util.Set;
  18 
  19 /**
  20  * Hash table based implementation of the <tt>Map</tt> interface.  This
  21  * implementation provides all of the optional map operations, and permits
  22  * <tt>null</tt> values and the <tt>null</tt> key.  (The <tt>HashMap</tt>
  23  * class is roughly equivalent to <tt>Hashtable</tt>, except that it is
  24  * unsynchronized and permits nulls.)  This class makes no guarantees as to
  25  * the order of the map; in particular, it does not guarantee that the order
  26  * will remain constant over time.
  27  *
  28  * <p>This implementation provides constant-time performance for the basic
  29  * operations (<tt>get</tt> and <tt>put</tt>), assuming the hash function
  30  * disperses the elements properly among the buckets.  Iteration over
  31  * collection views requires time proportional to the "capacity" of the
  32  * <tt>HashMap</tt> instance (the number of buckets) plus its size (the number
  33  * of key-value mappings).  Thus, it's very important not to set the initial
  34  * capacity too high (or the load factor too low) if iteration performance is
  35  * important.
  36  *
  37  * <p>An instance of <tt>HashMap</tt> has two parameters that affect its
  38  * performance: <i>initial capacity</i> and <i>load factor</i>.  The
  39  * <i>capacity</i> is the number of buckets in the hash table, and the initial
  40  * capacity is simply the capacity at the time the hash table is created.  The
  41  * <i>load factor</i> is a measure of how full the hash table is allowed to
  42  * get before its capacity is automatically increased.  When the number of
  43  * entries in the hash table exceeds the product of the load factor and the
  44  * current capacity, the hash table is <i>rehashed</i> (that is, internal data
  45  * structures are rebuilt) so that the hash table has approximately twice the
  46  * number of buckets.
  47  *
  48  * <p>As a general rule, the default load factor (.75) offers a good tradeoff
  49  * between time and space costs.  Higher values decrease the space overhead
  50  * but increase the lookup cost (reflected in most of the operations of the
  51  * <tt>HashMap</tt> class, including <tt>get</tt> and <tt>put</tt>).  The
  52  * expected number of entries in the map and its load factor should be taken
  53  * into account when setting its initial capacity, so as to minimize the
  54  * number of rehash operations.  If the initial capacity is greater
  55  * than the maximum number of entries divided by the load factor, no
  56  * rehash operations will ever occur.
  57  *
  58  * <p>If many mappings are to be stored in a <tt>HashMap</tt> instance,
  59  * creating it with a sufficiently large capacity will allow the mappings to
  60  * be stored more efficiently than letting it perform automatic rehashing as
  61  * needed to grow the table.
  62  *
  63  * <p><strong>Note that this implementation is not synchronized.</strong>
  64  * If multiple threads access a hash map concurrently, and at least one of
  65  * the threads modifies the map structurally, it <i>must</i> be
  66  * synchronized externally.  (A structural modification is any operation
  67  * that adds or deletes one or more mappings; merely changing the value
  68  * associated with a key that an instance already contains is not a
  69  * structural modification.)  This is typically accomplished by
  70  * synchronizing on some object that naturally encapsulates the map.
  71  *
  72  * If no such object exists, the map should be "wrapped" using the
  73  * {@link Collections#synchronizedMap Collections.synchronizedMap}
  74  * method.  This is best done at creation time, to prevent accidental
  75  * unsynchronized access to the map:<pre>
  76  *   Map m = Collections.synchronizedMap(new HashMap(...));</pre>
  77  *
  78  * <p>The iterators returned by all of this class's "collection view methods"
  79  * are <i>fail-fast</i>: if the map is structurally modified at any time after
  80  * the iterator is created, in any way except through the iterator's own
  81  * <tt>remove</tt> method, the iterator will throw a
  82  * {@link ConcurrentModificationException}.  Thus, in the face of concurrent
  83  * modification, the iterator fails quickly and cleanly, rather than risking
  84  * arbitrary, non-deterministic behavior at an undetermined time in the
  85  * future.
  86  *
  87  * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
  88  * as it is, generally speaking, impossible to make any hard guarantees in the
  89  * presence of unsynchronized concurrent modification.  Fail-fast iterators
  90  * throw <tt>ConcurrentModificationException</tt> on a best-effort basis.
  91  * Therefore, it would be wrong to write a program that depended on this
  92  * exception for its correctness: <i>the fail-fast behavior of iterators
  93  * should be used only to detect bugs.</i>
  94  *
  95  * <p>This class is a member of the
  96  * <a href="{@docRoot}/../technotes/guides/collections/index.html">
  97  * Java Collections Framework</a>.
  98  *
  99  * @param <K> the type of keys maintained by this map
 100  * @param <V> the type of mapped values
 101  *
 102  * @author  Doug Lea
 103  * @author  Josh Bloch
 104  * @author  Arthur van Hoff
 105  * @author  Neal Gafter
 106  * @version %I%, %G%
 107  * @see     Object#hashCode()
 108  * @see     Collection
 109  * @see        Map
 110  * @see        TreeMap
 111  * @see        Hashtable
 112  * @since   1.2
 113  */
 114 
 115 public class HashMap<K,V>
 116     extends AbstractMap<K,V>
 117     implements Map<K,V>, Cloneable, Serializable
 118 {
 119 
 120     /**
 121      * The default initial capacity - MUST be a power of two.
 122      * 默认初始化容量为16---必须是2的次幂
 123      */
 124     static final int DEFAULT_INITIAL_CAPACITY = 16;
 125 
 126     /**
 127      * The maximum capacity, used if a higher value is implicitly specified
 128      * by either of the constructors with arguments.
 129      * MUST be a power of two <= 1<<30.
 130      * 最大的容量,当一个比较大的值通过构造器明确指出容器的容量是会被使用到,2的次幂小于等于1<<30
 131      */
 132     static final int MAXIMUM_CAPACITY = 1 << 30;
 133 
 134     /**
 135      * The load factor used when none specified in constructor.
 136      * 当构造器没有明确指出时,默认的负载因子,默认的负载因子为 0.75f
 137      */
 138     static final float DEFAULT_LOAD_FACTOR = 0.75f;
 139 
 140     /**
 141      * The table, resized as necessary. Length MUST Always be a power of two.
 142      * 哈希表,大小根据需要调整,长度必须是2的次幂
 143      */
 144     transient Entry[] table;
 145 
 146     /**
 147      * The number of key-value mappings contained in this map.
 148      * HashMap实际存储key-value键值对的数量
 149      */
 150     transient int size;
 151 
 152     /**
 153      * The next size value at which to resize (capacity * load factor).
 154      * HashMap再次调整大小的阈值,该阈值的计算公式为(threshold = capacity * loadFactor)
 155      * (该阶段的阈值 = 该阶段的容器的容量 * 负载因子)
 156      * @serial
 157      */
 158     int threshold;
 159 
 160     /**
 161      * The load factor for the hash table.
 162      * 哈希表的负载因子
 163      * @serial
 164      */
 165     final float loadFactor;
 166 
 167     /**
 168      * The number of times this HashMap has been structurally modified
 169      * Structural modifications are those that change the number of mappings in
 170      * the HashMap or otherwise modify its internal structure (e.g.,
 171      * rehash).  This field is used to make iterators on Collection-views of
 172      * the HashMap fail-fast.  (See ConcurrentModificationException).
 173      * 用于记录HashMap结构性修改的次数,结构性的修改是改变HashMap中key-value键值对的数量,或者是修改他内部的结构,
 174      * 该属性是为了在HashMap集合视图变量的时候,当出现并发修改的时候,产生快速失败,抛出 ConcurrentModificationException
 175      */
 176     transient volatile int modCount;
 177 
 178     /**
 179      * Constructs an empty <tt>HashMap</tt> with the specified initial
 180      * capacity and load factor.
 181      * 构造一个包含指定初始化容量和负载因子的空的HashMap
 182      * @param  initialCapacity the initial capacity
 183      * 参数:初始化容量
 184      * @param  loadFactor      the load factor
 185      * 参数:负载因子
 186      * @throws IllegalArgumentException if the initial capacity is negative
 187      *         or the load factor is nonpositive
 188      * 如果初始化容量是负数的或者负载因子是非正的,抛出IllegalArgumentException
 189      */
 190     public HashMap(int initialCapacity, float loadFactor) {
 191         //判断初始化容量是否小于零,如果小于零抛出非法的参数异常(IllegalArgumentException)
 192         if (initialCapacity < 0)
 193             throw new IllegalArgumentException("Illegal initial capacity: " +
 194                                                initialCapacity);
 195         //判断初始化容量是否是最大容量2的30次方(1<<30),如果大于最大值,初始化容量只能为最大值
 196         if (initialCapacity > MAXIMUM_CAPACITY)
 197             initialCapacity = MAXIMUM_CAPACITY;
 198         //判断负载因子是否小于等于零或者不是一个数,抛出非法的参数异常(IllegalArgumentException)
 199         //Java.lang.Float.isNaN()方法 : 
 200         //此方法如果此对象所表示的值是NaN(Not a Number不是一个数),返回true,否则返回false
 201         if (loadFactor <= 0 || Float.isNaN(loadFactor))
 202             throw new IllegalArgumentException("Illegal load factor: " +
 203                                                loadFactor);
 204 
 205         // Find a power of 2 >= initialCapacity
 206         // 找到一个大于等于传入的initialCapacity初始化容量的2的次幂,作为容量HashMap的初始化容量
 207         int capacity = 1;
 208         while (capacity < initialCapacity)
 209             capacity <<= 1;
 210         //负载因子赋值
 211         this.loadFactor = loadFactor;
 212         //根据上述阈值公式计算阈值
 213         threshold = (int)(capacity * loadFactor);
 214         //根据找到的2的次幂的容量,初始化Entry数组,大小为找到的容量
 215         table = new Entry[capacity];
 216         init();
 217     }
 218 
 219     /**
 220      * Constructs an empty <tt>HashMap</tt> with the specified initial
 221      * capacity and the default load factor (0.75).
 222      * 构造一个包含指定初始化容量和默认负载因子的空的HashMap
 223      *
 224      * @param  initialCapacity the initial capacity.
 225      * 参数:初始化容量
 226      * @throws IllegalArgumentException if the initial capacity is negative.
 227      * 异常:在初始化容量为负数是抛出IllegalArgumentException
 228      */
 229     public HashMap(int initialCapacity) {
 230         //调用重载的构造器
 231         this(initialCapacity, DEFAULT_LOAD_FACTOR);
 232     }
 233 
 234     /**
 235      * Constructs an empty <tt>HashMap</tt> with the default initial capacity
 236      * (16) and the default load factor (0.75).
 237      * 构造一个包含默认初始化容量(16)和默认负载因子(0.75)的空的HashMap
 238      */
 239     public HashMap() {
 240         //负载因子赋值0.75
 241         this.loadFactor = DEFAULT_LOAD_FACTOR;
 242         //根据上述阈值公式计算阈值
 243         threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR);//12 = 16 * 0.75
 244         //初始化Entry数组
 245         table = new Entry[DEFAULT_INITIAL_CAPACITY];
 246         init();
 247     }
 248 
 249     /**
 250      * Constructs a new <tt>HashMap</tt> with the same mappings as the
 251      * specified <tt>Map</tt>.  The <tt>HashMap</tt> is created with
 252      * default load factor (0.75) and an initial capacity sufficient to
 253      * hold the mappings in the specified <tt>Map</tt>.
 254      * 根据指定的Map创建HashMap,该HashMap的负载因子是默认负载因子0.75和一个足够能够容纳这个Map的初始化容量
 255      * @param   m the map whose mappings are to be placed in this map
 256      * 参数:将要被放置在这个HashMap中的Map
 257      * @throws  NullPointerException if the specified map is null
 258      * 异常:当这个指定的Map是null是抛出NullPointException
 259      */
 260     public HashMap(Map<? extends K, ? extends V> m) {
 261         this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1,
 262                       DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR);
 263         //threshold = capacity * loadFactor => capacity = threshold/loadFactor
 264         //调用第一个重载的构造器,选择初始化容量为(Map的大小(将其看作新建HashMap的阈值)/默认负载因子 + 1)和默认初始化容量相比较较大的那个
 265         // 将Map放入新构造的HashMap
 266         putAllForCreate(m);
 267     }
 268 
 269     // internal utilities
 270 
 271     /**
 272      * Initialization hook for subclasses. This method is called
 273      * in all constructors and pseudo-constructors (clone, readObject)
 274      * after HashMap has been initialized but before any entries have
 275      * been inserted.  (In the absence of this method, readObject would
 276      * require explicit knowledge of subclasses.)
 277      * 子类初始化的钩子方法,在所有的构造器和伪构造器(例如 clone和readObject方法)中调用
 278      * 而且是在HashMap被初始化之后,任何键值对被添加之前(如果这个方法不存在,readObject必须清楚的知道子类的情况)
 279      */
 280     void init() {
 281     }
 282 
 283     /**
 284      * Applies a supplemental hash function to a given hashCode, which
 285      * defends against poor quality hash functions.  This is critical
 286      * because HashMap uses power-of-two length hash tables, that
 287      * otherwise encounter collisions for hashCodes that do not differ
 288      * in lower bits. Note: Null keys always map to hash 0, thus index 0.
 289      * 对于给予的hashcode,进一步处理,避免了糟糕的hash表的性能,这个至关重要的,因为HashMap用的是2的次幂长度的hash表
 290      * 否则在没有差别的hashcode就会遭遇碰撞 
 291      * 注意:key值为null的map的hash值是0,因此索引也就是一直为0
 292      */
 293     static int hash(int h) {
 294         // This function ensures that hashCodes that differ only by
 295         // constant multiples at each bit position have a bounded
 296         // number of collisions (approximately 8 at default load factor).
 297         // 这个函数确保只有不同常量倍数的hashcode
 298         // 在每个位置上有限的碰撞次数(在默认的负载因子的情况大约是8)
 299         h ^= (h >>> 20) ^ (h >>> 12);
 300         return h ^ (h >>> 7) ^ (h >>> 4);
 301     }
 302 
 303     /**
 304      * Returns index for hash code h.
 305      * 根据hash值,返回索引
 306      */
 307     static int indexFor(int h, int length) {
 308         //hash值的取模操作,因为length保证是2的次幂
 309         //则 h%length <==> h & (length-1)
 310         //但是&操作效率高于%的操作效率
 311         return h & (length-1);
 312     }
 313 
 314     /**
 315      * Returns the number of key-value mappings in this map.
 316      * 
 317      * @return the number of key-value mappings in this map
 318      * 返回该Map中的Key-Value键值对的实际数目
 319      */
 320     public int size() {
 321         return size;
 322     }
 323 
 324     /**
 325      * Returns <tt>true</tt> if this map contains no key-value mappings.
 326      *
 327      * @return <tt>true</tt> if this map contains no key-value mappings
 328      * 如果没有键值对返回true
 329      */
 330     public boolean isEmpty() {
 331         return size == 0;
 332     }
 333 
 334     /**
 335      * Returns the value to which the specified key is mapped,
 336      * or {@code null} if this map contains no mapping for the key.
 337      * 返回指定Key对应的Value值,如果没有返回null      
 338      * <p>More formally, if this map contains a mapping from a key
 339      * {@code k} to a value {@code v} such that {@code (key==null ? k==null :
 340      * key.equals(k))}, then this method returns {@code v}; otherwise
 341      * it returns {@code null}.  (There can be at most one such mapping.)
 342      * 更正式点说,如果存在这样个map(key==null ? k==null : key.equals(k)
 343      * 返回value,否则返回null,最多只有一个这个的键值对
 344      * <p>A return value of {@code null} does not <i>necessarily</i>
 345      * indicate that the map contains no mapping for the key; it's also
 346      * possible that the map explicitly maps the key to {@code null}.
 347      * The {@link #containsKey containsKey} operation may be used to
 348      * distinguish these two cases.
 349      * 并不一定会返回null,如果返回null值,表示不存在指定key的map,或者可能是该key的Value就是null
 350      * 可以通过containsKey操作来判别
 351      * @see #put(Object, Object)
 352      */
 353     public V get(Object key) {
 354         //如果Key等于null
 355         if (key == null)
 356             return getForNullKey();
 357         //根据hash值计算索引,遍历该索引下的链表,满足条件返回value
 358         int hash = hash(key.hashCode());
 359         for (Entry<K,V> e = table[indexFor(hash, table.length)];
 360              e != null;
 361              e = e.next) {
 362             Object k;
 363             if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
 364                 return e.value;
 365         }
 366         return null;
 367     }
 368 
 369     /**
 370      * Offloaded version of get() to look up null keys.  Null keys map
 371      * to index 0.  This null case is split out into separate methods
 372      * for the sake of performance in the two most commonly used
 373      * operations (get and put), but incorporated with conditionals in
 374      * others.
 375      * get()方法的分支查找为null的键值,null的键值对应的索引是0,
 376      * 分别针对get和put的情况,null值的特例被分出来,同时结合了其他条件
 377      */
 378     private V getForNullKey() {
 379         //遍历该索引下的链表,找到Key为null的Value返回,找不到返回null
 380         for (Entry<K,V> e = table[0]; e != null; e = e.next) {
 381             if (e.key == null)
 382                 return e.value;
 383         }
 384         return null;
 385     }
 386 
 387     /**
 388      * Returns <tt>true</tt> if this map contains a mapping for the
 389      * specified key.
 390      * 如果存在,指定key对用的键值对返回true
 391      * @param   key   The key whose presence in this map is to be tested
 392      * @return <tt>true</tt> if this map contains a mapping for the specified
 393      * key.
 394      */
 395     public boolean containsKey(Object key) {
 396         return getEntry(key) != null;
 397     }
 398 
 399     /**
 400      * Returns the entry associated with the specified key in the
 401      * HashMap.  Returns null if the HashMap contains no mapping
 402      * for the key.
 403      * 根据指定key值返回对应的键值对对象,如果不存在这样的键值对返回null
 404      */
 405     final Entry<K,V> getEntry(Object key) {
 406         int hash = (key == null) ? 0 : hash(key.hashCode());
 407         for (Entry<K,V> e = table[indexFor(hash, table.length)];
 408              e != null;
 409              e = e.next) {
 410             Object k;
 411             if (e.hash == hash &&
 412                 ((k = e.key) == key || (key != null && key.equals(k))))
 413                 return e;
 414         }
 415         return null;
 416     }
 417 
 418 
 419     /**
 420      * Associates the specified value with the specified key in this map.
 421      * If the map previously contained a mapping for the key, the old
 422      * value is replaced.
 423      * 将具体的Value和Key结合在一个Map中,如果之前存在过这样Key的键值对,该键值对
 424      * 的Value将被新Value覆盖
 425      * @param key key with which the specified value is to be associated
 426      * 参数:指定的Key
 427      * @param value value to be associated with the specified key
 428      * 参数:指定的Value
 429      * @return the previous value associated with <tt>key</tt>, or
 430      *         <tt>null</tt> if there was no mapping for <tt>key</tt>.
 431      *         (A <tt>null</tt> return can also indicate that the map
 432      *         previously associated <tt>null</tt> with <tt>key</tt>.)
 433      * 返回:返回Key值对应的旧的value值,或者如果没有对用Key相同的键值对返回null
 434      * 返回null值,也表明Key值之前对用的Value值就是null
 435      */
 436     public V put(K key, V value) {
 437         //判断Key是否等于null
 438         if (key == null)
 439             return putForNullKey(value);
 440         //根据hash值计算索引
 441         int hash = hash(key.hashCode());
 442         int i = indexFor(hash, table.length);
 443         //遍历哈希表,如果存在Key相等的情况,用新的Value值覆盖旧的Value值,返回旧的Value值
 444         for (Entry<K,V> e = table[i]; e != null; e = e.next) {
 445             Object k;
 446             if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
 447                 V oldValue = e.value;
 448                 e.value = value;
 449                 e.recordAccess(this);
 450                 return oldValue;
 451             }
 452         }
 453         //如果不存在Key相等的情况,修改结构性改变计数
 454         modCount++;
 455         //新增键值对,添加到链表中
 456         addEntry(hash, key, value, i);
 457         return null;
 458     }
 459 
 460     /**
 461      * Offloaded version of put for null keys
 462      * put在Key为null情况下的分支方法
 463      */
 464     private V putForNullKey(V value) {
 465         //如果已经存在Key值为null,这用新的Value代替旧的Value
 466         //否则增加修改计数
 467         //创建新的键值对,hash值为0,键值为null,索引为0
 468         for (Entry<K,V> e = table[0]; e != null; e = e.next) {
 469             if (e.key == null) {
 470                 V oldValue = e.value;
 471                 e.value = value;
 472                 e.recordAccess(this);
 473                 return oldValue;
 474             }
 475         }
 476         //如果不存在Key相等的情况,修改结构性改变计数
 477         modCount++;
 478         //新增键值对,添加到链表中
 479         addEntry(0, null, value, 0);
 480         return null;
 481     }
 482 
 483     /**
 484      * This method is used instead of put by constructors and
 485      * pseudoconstructors (clone, readObject).  It does not resize the table,
 486      * check for comodification, etc.  It calls createEntry rather than
 487      * addEntry.
 488      * 这个方法代替通过构造器和伪构造器(clone, readObject),
 489      * 不会调整哈希表和检查并发修改,调用createEntry而不是addEntry
 490      */
 491     private void putForCreate(K key, V value) {
 492         // 计算hash值,
 493         // 如果key为null---> hash值为0
 494         // 如果key不为null---> 获取key对象的hashCode值调用静态的hash的方法进一步处理,获取hash值
 495         int hash = (key == null) ? 0 : hash(key.hashCode());
 496         //根据hash值计算key值在哈希表中的索引
 497         int i = indexFor(hash, table.length);
 498 
 499         /**
 500          * Look for preexisting entry for key.  This will never happen for
 501          * clone or deserialize.  It will only happen for construction if the
 502          * input Map is a sorted map whose ordering is inconsistent w/ equals.
 503          * 根据key查找已经存在的键值对,这个不会在clone和deserialize中出现,
 504          * 只会在这个Map是一个与放入顺序或者equals不一致的有序Map中出现
 505          */
 506         //变量HashMap的键值对,如果存在Key相等则直接用Value新值直接覆盖原来Value的旧值
 507         //注意:这里有两种情况,前提两者的hash值要相等 1. == 进行相比 2. equals进行相比 
 508         for (Entry<K,V> e = table[i]; e != null; e = e.next) {
 509             Object k;
 510             if (e.hash == hash &&
 511                 ((k = e.key) == key || (key != null && key.equals(k)))) {
 512                 e.value = value;
 513                 return;
 514             }
 515         }
 516         //如果没有key值相等的情况则创建新的结点
 517         createEntry(hash, key, value, i);
 518     }
 519 
 520     private void putAllForCreate(Map<? extends K, ? extends V> m) {
 521         //遍历Map,获取Key和Value,各自调用putForCreate方法
 522         for (Iterator<? extends Map.Entry<? extends K, ? extends V>> i = m.entrySet().iterator(); i.hasNext(); ) {
 523             Map.Entry<? extends K, ? extends V> e = i.next();
 524             putForCreate(e.getKey(), e.getValue());
 525         }
 526     }
 527 
 528     /**
 529      * Rehashes the contents of this map into a new array with a
 530      * larger capacity.  This method is called automatically when the
 531      * number of keys in this map reaches its threshold.
 532      * 再一次将Map中的内容放到一个新的更大容量的数组中去,当Map中的键值数量达到阈值的时候会调用这个方法
 533      * If current capacity is MAXIMUM_CAPACITY, this method does not
 534      * resize the map, but sets threshold to Integer.MAX_VALUE.
 535      * This has the effect of preventing future calls.
 536      * 如果当前的容量是HashMap的最大容量时,这个方法不会重新调整Map的大小,但是会把HashMap的阈值设置为Integer的最大值
 537      * 这就阻止了再次调用的发生
 538      * @param newCapacity the new capacity, MUST be a power of two;
 539      *        must be greater than current capacity unless current
 540      *        capacity is MAXIMUM_CAPACITY (in which case value
 541      *        is irrelevant).
 542      * 参数:newCapacity新的容量,必须是2的次幂,必须大于当前的容量,除非当前容量是最大容量
 543      * (如果在这种情况下,该容量值也是不起作用的)
 544      */
 545     void resize(int newCapacity) {
 546         //1.将存放Map的Entry数组,临时存放起来到oldTable
 547         //2.获取旧的容量,并判断是否等于最大容量,如果等于最大容量,将阈值该为Integer的最大值,不进行调整大小直接返回
 548         //3.用newCapacity创建一个同样大小的Entry数组,这就是扩容后的新的数组容器
 549         //4.调用transfer方法进行复制,将所有的价值对搬移到新的容器中
 550         //5.table重新赋值,阈值重新计算
 551         Entry[] oldTable = table;
 552         int oldCapacity = oldTable.length;
 553         if (oldCapacity == MAXIMUM_CAPACITY) {
 554             threshold = Integer.MAX_VALUE;
 555             return;
 556         }
 557 
 558         Entry[] newTable = new Entry[newCapacity];
 559         transfer(newTable);
 560         table = newTable;
 561         threshold = (int)(newCapacity * loadFactor);
 562     }
 563 
 564     /**
 565      * Transfers all entries from current table to newTable.
 566      * 将所有的键值对从当前的表搬到新的表,实质数组的复制
 567      */
 568     void transfer(Entry[] newTable) {
 569         //获取旧的table
 570         Entry[] src = table;
 571         int newCapacity = newTable.length;
 572         //遍历旧的键值对数组
 573         for (int j = 0; j < src.length; j++) {
 574             //获取一个桶的链表,对链表进行搬移
 575             Entry<K,V> e = src[j];
 576             //如果当前桶不为空,说明存在链表
 577             if (e != null) {
 578                 //有助于垃圾回收
 579                 src[j] = null;
 580                 //遍历当前链表,知道链表为有结点为null为止
 581                 do {
 582                     //获取链表的下一个节点的价值对对象
 583                     Entry<K,V> next = e.next;
 584                     //根据新的容量重新计算索引
 585                     int i = indexFor(e.hash, newCapacity);
 586                     //维护链表的结构是需要通过每个节点的next属性来做的
 587                     //可以这么认为table[i]/newTable[i]就是该链表的一个元素,因为新添加的元素总是要放在链表的第一个位置
 588                     //那怎么连起来呢?就要将newTable[i]作为新元素节点的下个节点(e.next = newTable[i]),
 589                     // 而将新元素赋值给newTable[i](newTable[i] = e)
 590                     e.next = newTable[i];
 591                     newTable[i] = e;
 592                     //为下一次循环做准备
 593                     e = next;
 594                 } while (e != null);
 595             }
 596         }
 597     }
 598 
 599     /**
 600      * Copies all of the mappings from the specified map to this map.
 601      * These mappings will replace any mappings that this map had for
 602      * any of the keys currently in the specified map.
 603      * 将指定的Map复制到当前的Map中,对于指定Map有Key和当前Map重复的,这些键值对都会被替换掉
 604      * @param m mappings to be stored in this map
 605      * 参数:存储键值对的Map
 606      * @throws NullPointerException if the specified map is null
 607      * 异常:如果指定的Map为null,将会抛出NullPointerException
 608      */
 609     public void putAll(Map<? extends K, ? extends V> m) {
 610         int numKeysToBeAdded = m.size();
 611         if (numKeysToBeAdded == 0)
 612             return;
 613 
 614         /*
 615          * Expand the map if the map if the number of mappings to be added
 616          * is greater than or equal to threshold.  This is conservative; the
 617          * obvious condition is (m.size() + size) >= threshold, but this
 618          * condition could result in a map with twice the appropriate capacity,
 619          * if the keys to be added overlap with the keys already in this map.
 620          * By using the conservative calculation, we subject ourself
 621          * to at most one extra resize.
 622          * 如果加入的键值对的数量大于或者等于阈值,就会对Map进行扩容
 623          * 这是一种保守的做法,很明显的条件是(m.size() + size) >= threshold
 624          * 但是,如果被添加的Keys与当前的Map中的Keys重复,这种条件可能导致Map的容量是合适容量的两倍
 625          * 通过使用保守的计算方式,将会导致至多一次的扩容操作。
 626          */
 627         if (numKeysToBeAdded > threshold) {
 628             int targetCapacity = (int)(numKeysToBeAdded / loadFactor + 1);
 629             if (targetCapacity > MAXIMUM_CAPACITY)
 630                 targetCapacity = MAXIMUM_CAPACITY;
 631             int newCapacity = table.length;
 632             while (newCapacity < targetCapacity)
 633                 newCapacity <<= 1;
 634             if (newCapacity > table.length)
 635                 resize(newCapacity);
 636         }
 637         //遍历Map的Key和Value放入
 638         for (Iterator<? extends Map.Entry<? extends K, ? extends V>> i = m.entrySet().iterator(); i.hasNext(); ) {
 639             Map.Entry<? extends K, ? extends V> e = i.next();
 640             put(e.getKey(), e.getValue());
 641         }
 642     }
 643 
 644     /**
 645      * Removes the mapping for the specified key from this map if present.
 646      * 根据指定的Key删除键值对,如果存在
 647      * @param  key key whose mapping is to be removed from the map
 648      * @return the previous value associated with <tt>key</tt>, or
 649      *         <tt>null</tt> if there was no mapping for <tt>key</tt>.
 650      *         (A <tt>null</tt> return can also indicate that the map
 651      *         previously associated <tt>null</tt> with <tt>key</tt>.)
 652      *  返回值为null代表两种情况,第一,不存在指定的Key对应的键值对,第二,key值对应的Value值就是null
 653      */
 654     public V remove(Object key) {
 655         Entry<K,V> e = removeEntryForKey(key);
 656         return (e == null ? null : e.value);
 657     }
 658 
 659     /**
 660      * Removes and returns the entry associated with the specified key
 661      * in the HashMap.  Returns null if the HashMap contains no mapping
 662      * for this key.
 663      * 根据指定的Key,删除并返回键值对对象,返回为null,表示该HashMap中不含该Key对应的键值对
 664      */
 665     final Entry<K,V> removeEntryForKey(Object key) {
 666         int hash = (key == null) ? 0 : hash(key.hashCode());
 667         int i = indexFor(hash, table.length);
 668         Entry<K,V> prev = table[i];
 669         Entry<K,V> e = prev;
 670 
 671         while (e != null) {
 672             Entry<K,V> next = e.next;
 673             Object k;
 674             if (e.hash == hash &&
 675                 ((k = e.key) == key || (key != null && key.equals(k)))) {
 676                 modCount++;
 677                 size--;
 678                 //如果就是链表的第一个元素,直接将链表的下一阶段next指向,链表头部
 679                 if (prev == e)
 680                     table[i] = next;
 681                 else
 682                     //前节点的next节点直接指向,当前节点的next节点,也就删除了当前节点在链表中的位置
 683                     prev.next = next;
 684                 e.recordRemoval(this);
 685                 return e;
 686             }
 687             //将做过循环的判断的e,作为下次循环的前一个节点
 688             prev = e;
 689             //将next作为下个循环节点
 690             e = next;
 691         }
 692 
 693         return e;
 694     }
 695 
 696     /**
 697      * Special version of remove for EntrySet.
 698      * 针对entryset的删除
 699      */
 700     //总体来说给removeEntryForKey没什么大的差别,添加了一下两点
 701     final Entry<K,V> removeMapping(Object o) {
 702         //1.添加了对于对象类型的判断
 703         if (!(o instanceof Map.Entry))
 704             return null;
 705 
 706         Map.Entry<K,V> entry = (Map.Entry<K,V>) o;
 707         //2.获取Key值,而这是在removeEntryForKey方法中直接传入的
 708         Object key = entry.getKey();
 709         int hash = (key == null) ? 0 : hash(key.hashCode());
 710         int i = indexFor(hash, table.length);
 711         Entry<K,V> prev = table[i];
 712         Entry<K,V> e = prev;
 713 
 714         while (e != null) {
 715             Entry<K,V> next = e.next;
 716             if (e.hash == hash && e.equals(entry)) {
 717                 modCount++;
 718                 size--;
 719                 if (prev == e)
 720                     table[i] = next;
 721                 else
 722                     prev.next = next;
 723                 e.recordRemoval(this);
 724                 return e;
 725             }
 726             prev = e;
 727             e = next;
 728         }
 729 
 730         return e;
 731     }
 732 
 733     /**
 734      * Removes all of the mappings from this map.
 735      * The map will be empty after this call returns.
 736      * 清空HashMap
 737      */
 738     public void clear() {
 739         modCount++;
 740         Entry[] tab = table;
 741         for (int i = 0; i < tab.length; i++)
 742             tab[i] = null;
 743         size = 0;
 744     }
 745 
 746     /**
 747      * Returns <tt>true</tt> if this map maps one or more keys to the
 748      * specified value.
 749      * 如果有一个或者多个键值对包含指定的Value值则返回true
 750      * @param value value whose presence in this map is to be tested
 751      * @return <tt>true</tt> if this map maps one or more keys to the
 752      *         specified value
 753      */
 754     public boolean containsValue(Object value) {
 755      //如果为null做特殊处理
 756     if (value == null)
 757             return containsNullValue();
 758     //遍历Map,找到是否有Value值与参数相等的,注意比较是equals的比较
 759     Entry[] tab = table;
 760         for (int i = 0; i < tab.length ; i++)
 761             for (Entry e = tab[i] ; e != null ; e = e.next)
 762                 if (value.equals(e.value))
 763                     return true;
 764     return false;
 765     }
 766 
 767     /**
 768      * Special-case code for containsValue with null argument
 769      * 针对containsValue方法参数为null的特殊性做处理
 770      * 遍历Map,寻找是否有Value为null的键值对
 771      */
 772     private boolean containsNullValue() {
 773     Entry[] tab = table;
 774         for (int i = 0; i < tab.length ; i++)
 775             for (Entry e = tab[i] ; e != null ; e = e.next)
 776                 if (e.value == null)
 777                     return true;
 778     return false;
 779     }
 780 
 781     /**
 782      * Returns a shallow copy of this <tt>HashMap</tt> instance: the keys and
 783      * values themselves are not cloned.
 784      * 返回当前HashMap实例的浅克隆,keys和values他们自身并没克隆
 785      * @return a shallow copy of this map
 786      */
 787     public Object clone() {
 788         HashMap<K,V> result = null;
 789     try {
 790         //调用父类开始clone
 791         result = (HashMap<K,V>)super.clone();
 792     } catch (CloneNotSupportedException e) {
 793         // assert false;
 794     }
 795         result.table = new Entry[table.length];
 796         result.entrySet = null;
 797         result.modCount = 0;
 798         result.size = 0;
 799         result.init();
 800         //遍历放置当前的Map所有键值对到,克隆的result中,就像HashMap的下面的构造方法一样
 801         // public HashMap(Map<? extends K, ? extends V> m) {}
 802         result.putAllForCreate(this);
 803 
 804         return result;
 805     }
 806     //键值对静态内部类
 807     static class Entry<K,V> implements Map.Entry<K,V> {
 808         final K key;
 809         V value;
 810         Entry<K,V> next;
 811         final int hash;
 812 
 813         /**
 814          * Creates new entry.
 815          */
 816         Entry(int h, K k, V v, Entry<K,V> n) {
 817             value = v;
 818             next = n;
 819             key = k;
 820             hash = h;
 821         }
 822 
 823         public final K getKey() {
 824             return key;
 825         }
 826 
 827         public final V getValue() {
 828             return value;
 829         }
 830 
 831         public final V setValue(V newValue) {
 832         V oldValue = value;
 833             value = newValue;
 834             return oldValue;
 835         }
 836 
 837         public final boolean equals(Object o) {
 838             if (!(o instanceof Map.Entry))
 839                 return false;
 840             Map.Entry e = (Map.Entry)o;
 841             Object k1 = getKey();
 842             Object k2 = e.getKey();
 843             if (k1 == k2 || (k1 != null && k1.equals(k2))) {
 844                 Object v1 = getValue();
 845                 Object v2 = e.getValue();
 846                 if (v1 == v2 || (v1 != null && v1.equals(v2)))
 847                     return true;
 848             }
 849             return false;
 850         }
 851 
 852         public final int hashCode() {
 853             return (key==null   ? 0 : key.hashCode()) ^
 854                    (value==null ? 0 : value.hashCode());
 855         }
 856 
 857         public final String toString() {
 858             return getKey() + "=" + getValue();
 859         }
 860 
 861         /**
 862          * This method is invoked whenever the value in an entry is
 863          * overwritten by an invocation of put(k,v) for a key k that's already
 864          * in the HashMap.
 865          */
 866         //空方法,子类LinkedHashMap重写,实现功能
 867         void recordAccess(HashMap<K,V> m) {
 868         }
 869 
 870         /**
 871          * This method is invoked whenever the entry is
 872          * removed from the table.
 873          */
 874         //空方法,子类LinkedHashMap重写,实现功能
 875         void recordRemoval(HashMap<K,V> m) {
 876         }
 877     }
 878 
 879     /**
 880      * Adds a new entry with the specified key, value and hash code to
 881      * the specified bucket.  It is the responsibility of this
 882      * method to resize the table if appropriate.
 883      * 添加一个新的指定key,Value和hashCode到具体的索引的桶中,该方法会在合适的时候重新调整hash表的大小
 884      * Subclass overrides this to alter the behavior of put method.
 885      * 子类可以重写该方法修改put的行为
 886      */
 887     void addEntry(int hash, K key, V value, int bucketIndex) {
 888         //记录当前索引位置,将新建的键值对放在链表的第一位,该索引放在新建键值的next上
 889     Entry<K,V> e = table[bucketIndex];
 890         table[bucketIndex] = new Entry<K,V>(hash, key, value, e);
 891         //如果当前的键值对数量大于阈值,就要重新调整整个HashMap的大小,调整为之前容量的2倍
 892         if (size++ >= threshold)
 893             resize(2 * table.length);
 894     }
 895 
 896     /**
 897      * Like addEntry except that this version is used when creating entries
 898      * as part of Map construction or "pseudo-construction" (cloning,
 899      * deserialization).  This version needn't worry about resizing the table.
 900      * 这个方法很像addEntry方法,除了该版本可以应用于构造器或者伪构造器(clone,deserialization),将Map作为HashMap的一部分
 901      * 该版本并不需要担心重新调整Hash表,以为该方法用于初始化,在初始化的时候,已经保证了能够容纳Map的阈值了
 902      * Subclass overrides this to alter the behavior of HashMap(Map),
 903      * clone, and readObject.
 904      * 子类重写该方法,修改HashMap的clone,readObject的行为
 905      */
 906     void createEntry(int hash, K key, V value, int bucketIndex) {
 907     //将表索引暂时保存起来,代表链表的第一个节点,作为新建节点的下一个节点的指向
 908     //新添加的元素是要被放在链表的第一个位置的
 909     Entry<K,V> e = table[bucketIndex];
 910         table[bucketIndex] = new Entry<K,V>(hash, key, value, e);
 911         //key-Value键值对的实际值要增加
 912         size++;
 913     }
 914     //HashMap的迭代器的实现
 915     private abstract class HashIterator<E> implements Iterator<E> {
 916         Entry<K,V> next;    // next entry to return 下一个键值对
 917         int expectedModCount;    // For fast-fail 快速失败
 918         int index;        // current slot 当前位置
 919         Entry<K,V> current;    // current entry 当前键值对
 920 
 921         HashIterator() {
 922             expectedModCount = modCount;
 923             if (size > 0) { // advance to first entry
 924                 Entry[] t = table; //找到第一个不为null的桶
 925                 while (index < t.length && (next = t[index++]) == null)
 926                     ;
 927             }
 928         }
 929 
 930         public final boolean hasNext() {
 931             return next != null;
 932         }
 933 
 934         final Entry<K,V> nextEntry() {
 935             //并发修改判断,如果在遍历时,HashMap发生了结构性的变化,就会抛出异常
 936             if (modCount != expectedModCount)
 937                 throw new ConcurrentModificationException();
 938             Entry<K,V> e = next;
 939             //如果为null,表示遍历了所有都没找到,所以不存在
 940             if (e == null)
 941                 throw new NoSuchElementException();
 942             //一直遍历下去,直到找到所以元素
 943             if ((next = e.next) == null) {
 944                 Entry[] t = table;
 945                 while (index < t.length && (next = t[index++]) == null)
 946                     ;
 947             }
 948         current = e;
 949             return e;
 950         }
 951 
 952         public void remove() {
 953             if (current == null)
 954                 throw new IllegalStateException();
 955             if (modCount != expectedModCount)
 956                 throw new ConcurrentModificationException();
 957             Object k = current.key;
 958             current = null;
 959             //调用removeEntryForKey修改了modCount,
 960             HashMap.this.removeEntryForKey(k);
 961             //为了保证一致,避免并发异常
 962             expectedModCount = modCount;
 963         }
 964 
 965     }
 966     //Value迭代器
 967     private final class ValueIterator extends HashIterator<V> {
 968         public V next() {
 969             return nextEntry().value;
 970         }
 971     }
 972     //Key迭代器
 973     private final class KeyIterator extends HashIterator<K> {
 974         public K next() {
 975             return nextEntry().getKey();
 976         }
 977     }
 978     //Entry迭代器
 979     private final class EntryIterator extends HashIterator<Map.Entry<K,V>> {
 980         public Map.Entry<K,V> next() {
 981             return nextEntry();
 982         }
 983     }
 984 
 985     // Subclass overrides these to alter behavior of views' iterator() method
 986     Iterator<K> newKeyIterator()   {
 987         return new KeyIterator();
 988     }
 989     Iterator<V> newValueIterator()   {
 990         return new ValueIterator();
 991     }
 992     Iterator<Map.Entry<K,V>> newEntryIterator()   {
 993         return new EntryIterator();
 994     }
 995 
 996 
 997     // Views
 998 
 999     private transient Set<Map.Entry<K,V>> entrySet = null;
1000 
1001     /**
1002      * Returns a {@link Set} view of the keys contained in this map.
1003      * The set is backed by the map, so changes to the map are
1004      * reflected in the set, and vice-versa.  If the map is modified
1005      * while an iteration over the set is in progress (except through
1006      * the iterator's own <tt>remove</tt> operation), the results of
1007      * the iteration are undefined.  The set supports element removal,
1008      * which removes the corresponding mapping from the map, via the
1009      * <tt>Iterator.remove</tt>, <tt>Set.remove</tt>,
1010      * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt>
1011      * operations.  It does not support the <tt>add</tt> or <tt>addAll</tt>
1012      * operations.
1013      * 返回该map中包含的key的一个set集合,由于该set是由map支持的,所以改变map同样会映射到set集合中,反之亦然
1014      * 如果在set遍历的过程中,Map被修改(除非通过迭代器自己的remove方法),那迭代器的结果是不明确的
1015      * set集合支持元素的移除,从map中删除相应的键值对,可以通过Iterator.remove,Set.remove,removeAll,retainAll,clear
1016      * 不支持add和addAll
1017      */
1018     public Set<K> keySet() {
1019         Set<K> ks = keySet;
1020         return (ks != null ? ks : (keySet = new KeySet()));
1021     }
1022 
1023     private final class KeySet extends AbstractSet<K> {
1024         public Iterator<K> iterator() {
1025             return newKeyIterator();
1026         }
1027         public int size() {
1028             return size;
1029         }
1030         public boolean contains(Object o) {
1031             return containsKey(o);
1032         }
1033         public boolean remove(Object o) {
1034             return HashMap.this.removeEntryForKey(o) != null;
1035         }
1036         public void clear() {
1037             HashMap.this.clear();
1038         }
1039     }
1040 
1041     /**
1042      * Returns a {@link Collection} view of the values contained in this map.
1043      * The collection is backed by the map, so changes to the map are
1044      * reflected in the collection, and vice-versa.  If the map is
1045      * modified while an iteration over the collection is in progress
1046      * (except through the iterator's own <tt>remove</tt> operation),
1047      * the results of the iteration are undefined.  The collection
1048      * supports element removal, which removes the corresponding
1049      * mapping from the map, via the <tt>Iterator.remove</tt>,
1050      * <tt>Collection.remove</tt>, <tt>removeAll</tt>,
1051      * <tt>retainAll</tt> and <tt>clear</tt> operations.  It does not
1052      * support the <tt>add</tt> or <tt>addAll</tt> operations.
1053      */
1054     public Collection<V> values() {
1055         Collection<V> vs = values;
1056         return (vs != null ? vs : (values = new Values()));
1057     }
1058 
1059     private final class Values extends AbstractCollection<V> {
1060         public Iterator<V> iterator() {
1061             return newValueIterator();
1062         }
1063         public int size() {
1064             return size;
1065         }
1066         public boolean contains(Object o) {
1067             return containsValue(o);
1068         }
1069         public void clear() {
1070             HashMap.this.clear();
1071         }
1072     }
1073 
1074     /**
1075      * Returns a {@link Set} view of the mappings contained in this map.
1076      * The set is backed by the map, so changes to the map are
1077      * reflected in the set, and vice-versa.  If the map is modified
1078      * while an iteration over the set is in progress (except through
1079      * the iterator's own <tt>remove</tt> operation, or through the
1080      * <tt>setValue</tt> operation on a map entry returned by the
1081      * iterator) the results of the iteration are undefined.  The set
1082      * supports element removal, which removes the corresponding
1083      * mapping from the map, via the <tt>Iterator.remove</tt>,
1084      * <tt>Set.remove</tt>, <tt>removeAll</tt>, <tt>retainAll</tt> and
1085      * <tt>clear</tt> operations.  It does not support the
1086      * <tt>add</tt> or <tt>addAll</tt> operations.
1087      *
1088      * @return a set view of the mappings contained in this map
1089      */
1090     public Set<Map.Entry<K,V>> entrySet() {
1091     return entrySet0();
1092     }
1093 
1094     private Set<Map.Entry<K,V>> entrySet0() {
1095         Set<Map.Entry<K,V>> es = entrySet;
1096         return es != null ? es : (entrySet = new EntrySet());
1097     }
1098 
1099     private final class EntrySet extends AbstractSet<Map.Entry<K,V>> {
1100         public Iterator<Map.Entry<K,V>> iterator() {
1101             return newEntryIterator();
1102         }
1103         public boolean contains(Object o) {
1104             if (!(o instanceof Map.Entry))
1105                 return false;
1106             Map.Entry<K,V> e = (Map.Entry<K,V>) o;
1107             Entry<K,V> candidate = getEntry(e.getKey());
1108             return candidate != null && candidate.equals(e);
1109         }
1110         public boolean remove(Object o) {
1111             return removeMapping(o) != null;
1112         }
1113         public int size() {
1114             return size;
1115         }
1116         public void clear() {
1117             HashMap.this.clear();
1118         }
1119     }
1120 
1121     /**
1122      * Save the state of the <tt>HashMap</tt> instance to a stream (i.e.,
1123      * serialize it).
1124      * HashMap的序列化,将HashMap实例保存到一个流中
1125      * @serialData The <i>capacity</i> of the HashMap (the length of the
1126      *           bucket array) is emitted (int), followed by the
1127      *           <i>size</i> (an int, the number of key-value
1128      *           mappings), followed by the key (Object) and value (Object)
1129      *           for each key-value mapping.  The key-value mappings are
1130      *           emitted in no particular order.
1131      */
1132     private void writeObject(java.io.ObjectOutputStream s)
1133         throws IOException
1134     {
1135     Iterator<Map.Entry<K,V>> i =
1136         (size > 0) ? entrySet0().iterator() : null;
1137 
1138     // Write out the threshold, loadfactor, and any hidden stuff
1139     s.defaultWriteObject();
1140 
1141     // Write out number of buckets
1142     s.writeInt(table.length);
1143 
1144     // Write out size (number of Mappings)
1145     s.writeInt(size);
1146 
1147         // Write out keys and values (alternating)
1148     if (i != null) {
1149         while (i.hasNext()) {
1150         Map.Entry<K,V> e = i.next();
1151         s.writeObject(e.getKey());
1152         s.writeObject(e.getValue());
1153         }
1154         }
1155     }
1156 
1157     private static final long serialVersionUID = 362498820763181265L;
1158 
1159     /**
1160      * Reconstitute the <tt>HashMap</tt> instance from a stream (i.e.,
1161      * deserialize it).
1162      * 反序列化,重新构建HashMap
1163      */
1164     private void readObject(java.io.ObjectInputStream s)
1165          throws IOException, ClassNotFoundException
1166     {
1167     // Read in the threshold, loadfactor, and any hidden stuff
1168     s.defaultReadObject();
1169 
1170     // Read in number of buckets and allocate the bucket array;
1171     int numBuckets = s.readInt();
1172     table = new Entry[numBuckets];
1173 
1174         init();  // Give subclass a chance to do its thing.
1175 
1176     // Read in size (number of Mappings)
1177     int size = s.readInt();
1178 
1179     // Read the keys and values, and put the mappings in the HashMap
1180     for (int i=0; i<size; i++) {
1181         K key = (K) s.readObject();
1182         V value = (V) s.readObject();
1183         putForCreate(key, value);
1184     }
1185     }
1186 
1187     // These methods are used when serializing HashSets
1188     int   capacity()     { return table.length; }
1189     float loadFactor()   { return loadFactor;   }
1190 }

 

posted @ 2017-11-21 23:57  朱洪昌  阅读(423)  评论(0编辑  收藏  举报