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 }