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 }