hashMap 源码注释分析(一)
1 package MyHashMap; 2 3 import java.io.IOException; 4 import java.io.InvalidObjectException; 5 import java.io.Serializable; 6 import java.lang.reflect.ParameterizedType; 7 import java.lang.reflect.Type; 8 import java.util.*; 9 import java.util.function.BiConsumer; 10 import java.util.function.BiFunction; 11 import java.util.function.Consumer; 12 import java.util.function.Function; 13 import sun.misc.SharedSecrets; 14 15 16 17 public class HashMap<K,V> extends AbstractMap<K,V> 18 implements Map<K,V>, Cloneable, Serializable { 19 20 private static final long serialVersionUID = 362498820763181265L; 21 22 23 /** 24 * 默认初始容量-必须是2的幂。 25 */ 26 static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16 27 28 29 30 /** 31 * 最大容量。 32 *必须是2的幂<=1<<30。 33 */ 34 static final int MAXIMUM_CAPACITY = 1 << 30; 35 36 /** 37 * 构造函数中未指定时使用的加载因子。 38 */ 39 static final float DEFAULT_LOAD_FACTOR = 0.75f; 40 41 /** 42 * 使用树而不是数组作为储存数据的阈(yu)值 43 * 数组将转换为红黑树该值必须大于2,并且至少应为8, 44 */ 45 static final int TREEIFY_THRESHOLD = 8; 46 47 /** 48 * 在哈希表扩容时,如果发现链表长度小于 6,则会由树重新退化为链表 49 */ 50 static final int UNTREEIFY_THRESHOLD = 6; 51 52 /** 53 * 在转变成树之前,还会有一次判断,只有键值对数量大于 64 才会发生转换。 54 * 这是为了避免在哈希表建立初期,多个键值对恰好被放入了同一个链表中而导致不必要的转化 55 */ 56 static final int MIN_TREEIFY_CAPACITY = 64; 57 58 /** 59 * 当数组节点超过 TREEIFY_THRESHOLD 阈值时使用(有关TreeNode子类的信息,请参见下文,有关Entry子类的信息,请参见LinkedHashMap。) 60 * 61 * 该类为静态内部类,hashMap使用静态内部类创建链表 62 */ 63 static class Node<K,V> implements Map.Entry<K,V> { 64 final int hash; 65 final K key; 66 V value; 67 Node<K,V> next; 68 69 Node(int hash, K key, V value, Node<K,V> next) { 70 this.hash = hash; 71 this.key = key; 72 this.value = value; 73 this.next = next; 74 } 75 76 public final K getKey() { return key; } 77 public final V getValue() { return value; } 78 public final String toString() { return key + "=" + value; } 79 80 public final int hashCode() { 81 return Objects.hashCode(key) ^ Objects.hashCode(value); 82 } 83 84 public final V setValue(V newValue) { 85 V oldValue = value; 86 value = newValue; 87 return oldValue; 88 } 89 90 public final boolean equals(Object o) { 91 if (o == this) 92 return true; 93 if (o instanceof Map.Entry) { 94 Map.Entry<?,?> e = (Map.Entry<?,?>)o; 95 if (Objects.equals(key, e.getKey()) && 96 Objects.equals(value, e.getValue())) 97 return true; 98 } 99 return false; 100 } 101 } 102 103 /* ---------------- Static utilities -------------- */ 104 105 /** 106 * 计算key的hash值 107 * >>表示右移,如果该数为正,则高位补0,若为负数,则高位补1; 108 * >>>表示无符号右移,也叫逻辑右移,即若该数为正,则高位补0,而若该数为负数,则右移后高位同样补0。 109 * 使用key的hash值与该hash值右移16位异或 110 * 异或的定义,两个数的二进制表示进行按位异或,相同为0 , 相异为1, 111 */ 112 static final int hash(Object key) { 113 int h; 114 return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); 115 } 116 117 /** 118 * 如果x的类型实现Comparable<T> 返回x的 Class<?> 119 * 如果不是返回 null 120 */ 121 static Class<?> comparableClassFor(Object x) { 122 if (x instanceof Comparable) { 123 Class<?> c; Type[] ts, as; Type t; ParameterizedType p; 124 if ((c = x.getClass()) == String.class) // 将x.getClass() 赋值给c 125 return c; 126 if ((ts = c.getGenericInterfaces()) != null) { 127 for (int i = 0; i < ts.length; ++i) { 128 if (((t = ts[i]) instanceof ParameterizedType) && 129 ((p = (ParameterizedType)t).getRawType() == 130 Comparable.class) && 131 (as = p.getActualTypeArguments()) != null && 132 as.length == 1 && as[0] == c) // type arg is c 133 return c; 134 } 135 } 136 } 137 return null; 138 } 139 140 141 public static void main(String[] args) { 142 int n = 33 - 1; 143 System.out.println(Integer.toBinaryString(n)); 144 n |= n >>> 1; 145 System.out.println(Integer.toBinaryString(n)); 146 n |= n >>> 2; 147 System.out.println(Integer.toBinaryString(n)); 148 n |= n >>> 4; 149 System.out.println(Integer.toBinaryString(n)); 150 n |= n >>> 8; 151 System.out.println(Integer.toBinaryString(n)); 152 n |= n >>> 16; 153 System.out.println(n); 154 } 155 156 /** 157 * Returns k.compareTo(x) if x matches kc (k's screened comparable 158 * class), else 0. 159 */ 160 @SuppressWarnings({"rawtypes","unchecked"}) // for cast to Comparable 161 static int compareComparables(Class<?> kc, Object k, Object x) { 162 return (x == null || x.getClass() != kc ? 0 : 163 ((Comparable)k).compareTo(x)); 164 } 165 166 /** 167 * 对于给定的目标容量,返回两倍大小的幂。 168 */ 169 static final int tableSizeFor(int cap) { 170 int n = cap - 1; //保证容量值输入为2的幂时不会被再次扩容2倍 int n = 33 - 1; 100000 171 n |= n >>> 1;// 110000 n 与 n逻辑右移1位 赋值给n 目标为:把二进制数的所有位都变成1 172 // 1移1位与运算变成两个1 ,两个1移两位变成4个 4个变成8个 8个变16个 16个变32 覆盖所有的数 完成扩容。完美!!! 173 n |= n >>> 2;//111100 .... 174 n |= n >>> 4;//111111 ..... 175 n |= n >>> 8;//111111 176 n |= n >>> 16;//111111 177 return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1; 178 } 179 180 /* ---------------- Fields -------------- */ 181 182 /** 183 * transient修饰符的作用是使该变量在序列化的时候不会被储存。 184 * table是储存了容器中所有的元素(地址) 185 * HashMap的哈希桶数组,非常重要的存储结构,用于存放表示键值对数据的Node元素。 186 */ 187 transient Node<K,V>[] table; 188 189 /** 190 * HashMap将数据转换成set的另一种存储形式,这个变量主要用于迭代功能。 191 */ 192 transient Set<Map.Entry<K,V>> entrySet; 193 194 /** 195 * HashMap中实际存在的Node数量,注意这个数量不等于table的长度, 196 * 甚至可能大于它,因为在table的每个节点上是一个链表(或RBT)结构,可能不止有一个Node元素存在。 197 */ 198 transient int size; 199 200 /** 201 * HashMap的数据被修改的次数,这个变量用于迭代过程中的Fail-Fast机制, 202 * 其存在的意义在于保证发生了线程安全问题时,能及时的发现(操作前备份的count和当前modCount不相等)并抛出异常终止操作。 203 */ 204 transient int modCount; 205 206 /** 207 * The next size value at which to resize (capacity * load factor). 208 *HashMap的扩容阈值,在HashMap中存储的Node键值对超过这个数量时,自动扩容容量为原来的二倍。 209 * @serial 210 */ 211 // (The javadoc description is true upon serialization. 212 // Additionally, if the table array has not been allocated, this 213 // field holds the initial array capacity, or zero signifying 214 // DEFAULT_INITIAL_CAPACITY.) 215 int threshold; 216 217 /** 218 * HashMap的负载因子,可计算出当前table长度下的扩容阈值:threshold = loadFactor * table.length。 219 * 220 * @serial 221 */ 222 final float loadFactor; 223 224 /* ---------------- Public operations -------------- */ 225 226 /** 227 *hashMap的构造器, 228 * @param initialCapacity 初始化大小容量 默认16 229 * @param loadFactor 负载因子 默认0.75 230 * @throws IllegalArgumentException if the initial capacity is negative 231 * or the load factor is nonpositive 232 */ 233 public HashMap(int initialCapacity, float loadFactor) { 234 if (initialCapacity < 0) 235 throw new IllegalArgumentException("Illegal initial capacity: " + 236 initialCapacity); 237 if (initialCapacity > MAXIMUM_CAPACITY)//如果初始容量大于最大容量 则=最大容量 238 initialCapacity = MAXIMUM_CAPACITY; 239 if (loadFactor <= 0 || Float.isNaN(loadFactor)) 240 throw new IllegalArgumentException("Illegal load factor: " + 241 loadFactor); 242 this.loadFactor = loadFactor;//赋值负载因子 243 this.threshold = tableSizeFor(initialCapacity);//把容量转为范围内最大2的幂赋值给扩容阈值 244 } 245 246 /** 247 * Constructs an empty <tt>HashMap</tt> with the specified initial 248 * capacity and the default load factor (0.75). 249 * 250 * @param initialCapacity the initial capacity. 251 * @throws IllegalArgumentException if the initial capacity is negative. 252 */ 253 public HashMap(int initialCapacity) { 254 this(initialCapacity, DEFAULT_LOAD_FACTOR); 255 } 256 257 /** 258 * Constructs an empty <tt>HashMap</tt> with the default initial capacity 259 * (16) and the default load factor (0.75). 260 */ 261 public HashMap() { 262 this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted 263 } 264 265 /** 266 * Constructs a new <tt>HashMap</tt> with the same mappings as the 267 * specified <tt>Map</tt>. The <tt>HashMap</tt> is created with 268 * default load factor (0.75) and an initial capacity sufficient to 269 * hold the mappings in the specified <tt>Map</tt>. 270 * 271 * @param m the map whose mappings are to be placed in this map 272 * @throws NullPointerException if the specified map is null 273 */ 274 public HashMap(Map<? extends K, ? extends V> m) { 275 this.loadFactor = DEFAULT_LOAD_FACTOR; 276 putMapEntries(m, false); 277 } 278 279 /** 280 * Implements Map.putAll and Map constructor 281 * putALL 方法 把map添加到当前map中。 282 * 283 * @param m the map 284 * @param evict false when initially constructing this map, else 285 * true (relayed to method afterNodeInsertion). 286 */ 287 final void putMapEntries(Map<? extends K, ? extends V> m, boolean evict) { 288 int s = m.size(); 289 if (s > 0) { 290 if (table == null) { //如果map的容器是空的,没有初始化 291 float ft = ((float)s / loadFactor) + 1.0F; // threshold = loadFactor * table.length。计算容器需要的大小 292 int t = ((ft < (float)MAXIMUM_CAPACITY) ? 293 (int)ft : MAXIMUM_CAPACITY); 294 if (t > threshold)//如果容器大小大于当前的扩容阈值,则阈值扩容为范围内最大2的幂 295 threshold = tableSizeFor(t); 296 } 297 else if (s > threshold)//如果table 不为 null 且 传入的map的大小大于当前的扩容阈值 298 resize();//table 扩容 299 for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) {//给table赋值, 就是put操作 300 K key = e.getKey(); 301 V value = e.getValue(); 302 putVal(hash(key), key, value, false, evict);// put操作 303 } 304 } 305 }
HashMap 超详细注释解读