HashMap类成员说明(Jdk1.8)
本篇文章来给大家解读基于Jdk1.8环境下,HashMap的类成员变量和构造器以及重要内部类的代码
目录:
- 类成员变量
- HashMap构造器
- 重要内部类
1、类成员变量
1 /** 2 * The default initial capacity - MUST be a power of two. 3 * HashMap默认的初始化容量:16 4 */ 5 static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
1 /** 2 * The maximum capacity, used if a higher value is implicitly specified 3 * by either of the constructors with arguments. 4 * MUST be a power of two <= 1<<30. 5 * HashMap最大容量 6 */ 7 static final int MAXIMUM_CAPACITY = 1 << 30;
1 /** 2 * The load factor used when none specified in constructor. 3 * HashMap扩容机制的负载因子; 4 * 当添加元素数量达到容量的0.75倍时就触发数组扩容(初识容量时,当元素数量达到12就触发扩容) 5 */ 6 static final float DEFAULT_LOAD_FACTOR = 0.75f;
1 /** 2 * The bin count threshold for using a tree rather than list for a 3 * bin. Bins are converted to trees when adding an element to a 4 * bin with at least this many nodes. The value must be greater 5 * than 2 and should be at least 8 to mesh with assumptions in 6 * tree removal about conversion back to plain bins upon 7 * shrinkage. 8 * 链表转换为红黑树的阀值。 9 * 当数组index处的链表元素数量大于8,当第九个元素也冲突了,那么在添加第九个元素时index处的数据结构会转换为红黑树。 10 * 11 */ 12 static final int TREEIFY_THRESHOLD = 8;
1 /** 2 * The smallest table capacity for which bins may be treeified. 3 * (Otherwise the table is resized if too many nodes in a bin.) 4 * Should be at least 4 * TREEIFY_THRESHOLD to avoid conflicts 5 * between resizing and treeification thresholds. 6 * 红黑树的最小容量 7 */ 8 static final int MIN_TREEIFY_CAPACITY = 64;
1 /** 2 * The bin count threshold for untreeifying a (split) bin during a 3 * resize operation. Should be less than TREEIFY_THRESHOLD, and at 4 * most 6 to mesh with shrinkage detection under removal. 5 * 数组index处的结构是红黑树,当红黑树的元素数量等于6时,数据结构就转变为链表。 6 */ 7 static final int UNTREEIFY_THRESHOLD = 6;
1 /** 2 * The table, initialized on first use, and resized as 3 * necessary. When allocated, length is always a power of two. 4 * (We also tolerate length zero in some operations to allow 5 * bootstrapping mechanics that are currently not needed.) 6 * 7 * 当前属性就是真正的hashMap容器:Node数组,用于存放put进来的所有元素,都会封装成一个个Node对象添加到当前table容器中。 8 */ 9 transient Node<K,V>[] table;
1 /** 2 * Holds cached entrySet(). Note that AbstractMap fields are used 3 * for keySet() and values(). 4 * 5 * set对象,迭代器遍历HashMap时使用。 6 */ 7 transient Set<Map.Entry<K,V>> entrySet;
1 /** 2 * The number of key-value mappings contained in this map. 3 * 4 * size表示:用于表示当前table容器中存放的真正的元素数量,从1开始计数。 5 */ 6 transient int size;
1 /** 2 * The number of times this HashMap has been structurally modified 3 * Structural modifications are those that change the number of mappings in 4 * the HashMap or otherwise modify its internal structure (e.g., 5 * rehash). This field is used to make iterators on Collection-views of 6 * the HashMap fail-fast. (See ConcurrentModificationException). 7 * 8 * modCount表示:当前table容器被修改的次数。(添加元素和删除元素都算被修改1次都会做 ++modCount运算) 9 */ 10 transient int modCount;
1 /** 2 * The next size value at which to resize (capacity * load factor). 3 * 4 * threshold表示:table数组中的元素数量满多少个之后会触发扩容。 5 * 例如:首次table容器大小是16,那么 16*0.75=12,threshold就等于12,当数组元素数量添加到12个时就会触发扩容,下一次的table容量就是32,threshold就是24。 6 * @serial 7 */ 8 // (The javadoc description is true upon serialization. 9 // Additionally, if the table array has not been allocated, this 10 // field holds the initial array capacity, or zero signifying 11 // DEFAULT_INITIAL_CAPACITY.) 12 int threshold;
1 /** 2 * The load factor for the hash table. 3 * 当前表示容量的加载因子,说白了就是0.75,当前属性初始化时就是被 DEFAULT_LOAD_FACTOR 赋值的。 4 * 当元素数量等于table容量的0.75倍就要扩容了 5 * @serial 6 */ 7 final float loadFactor;
3、HashMap构造器
1 /** 2 * Constructs an empty <tt>HashMap</tt> with the specified initial 3 * capacity and load factor. 4 * HashMap的构造器 5 * 6 * @param initialCapacity the initial capacity 指定HashMap的初识容量 7 * @param loadFactor the load factor 指定HashMap的负载因子。(就是元素数量达到容量的多少倍时才会扩容) 8 * 9 * @throws IllegalArgumentException if the initial capacity is negative 10 * or the load factor is nonpositive 11 */ 12 public HashMap(int initialCapacity, float loadFactor) { 13 if (initialCapacity < 0) 14 throw new IllegalArgumentException("Illegal initial capacity: " + 15 initialCapacity); 16 // 如果入参中指定的HashMap的初识容量超过了内置的最大值, 17 // 则直接把内置的最大值赋值给初识容量,也就是说HashMap的最大容量只能是 2的30次方。 18 if (initialCapacity > MAXIMUM_CAPACITY) 19 initialCapacity = MAXIMUM_CAPACITY; 20 21 // 检查如果入参指定的负载因子小于等于0,则直接报错。 22 if (loadFactor <= 0 || Float.isNaN(loadFactor)) 23 throw new IllegalArgumentException("Illegal load factor: " + 24 loadFactor); 25 // 最后给HashMap的全局变量赋值 26 this.loadFactor = loadFactor; 27 this.threshold = tableSizeFor(initialCapacity); 28 }
1 /** 2 * Constructs an empty <tt>HashMap</tt> with the specified initial 3 * capacity and the default load factor (0.75). 4 * 5 * 有一个初识容量参数的构造器,使用默认的负载因子0.75倍 6 * 7 * @param initialCapacity the initial capacity. 8 * @throws IllegalArgumentException if the initial capacity is negative. 9 */ 10 public HashMap(int initialCapacity) { 11 this(initialCapacity, DEFAULT_LOAD_FACTOR); 12 }
1 /** 2 * Constructs an empty <tt>HashMap</tt> with the default initial capacity 3 * (16) and the default load factor (0.75). 4 * 无参的构造器,使用默认的负载因子0.75倍 5 */ 6 public HashMap() { 7 this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted 8 }
1 /** 2 * Constructs a new <tt>HashMap</tt> with the same mappings as the 3 * specified <tt>Map</tt>. The <tt>HashMap</tt> is created with 4 * default load factor (0.75) and an initial capacity sufficient to 5 * hold the mappings in the specified <tt>Map</tt>. 6 * 入参是一个Map的构造器,该构造器会将入参Map中的所有元素全部put到当前HashMap表中。 7 * 8 * @param m the map whose mappings are to be placed in this map 9 * @throws NullPointerException if the specified map is null 10 */ 11 public HashMap(Map<? extends K, ? extends V> m) { 12 this.loadFactor = DEFAULT_LOAD_FACTOR; 13 putMapEntries(m, false); 14 }
3、重要内部类
1 /** 2 * Basic hash bin node, used for most entries. (See below for 3 * TreeNode subclass, and in LinkedHashMap for its Entry subclass.) 4 * 5 * HashMap中的每一个元素都是Node对象 6 */ 7 static class Node<K,V> implements Map.Entry<K,V> { 8 // 元素的hash值 9 final int hash; 10 // 元素key 11 final K key; 12 // 元素值 13 V value; 14 // 当前元素的下一个元素,如果index处的数据结构是链表则有值。 15 Node<K,V> next; 16 17 // 构造器 18 Node(int hash, K key, V value, Node<K,V> next) { 19 this.hash = hash; 20 this.key = key; 21 this.value = value; 22 this.next = next; 23 } 24 }
1 /** 2 * 迭代器模式,一般遍历HashMap时使用。 3 * (一边删除元素一边修改或删除元素时,使用迭代器模式可防止并发修改的异常出现, 4 * 但是如果一边遍历一边向HashMap中添加元素,这种情况下迭代器模式也会报错,这种情况建议使用ConcurrentHashMap) 5 */ 6 final class EntrySet extends AbstractSet<Map.Entry<K,V>> { 7 public final int size() { return size; } 8 public final void clear() { HashMap.this.clear(); } 9 public final Iterator<Map.Entry<K,V>> iterator() { 10 return new EntryIterator(); 11 } 12 public final boolean contains(Object o) { 13 if (!(o instanceof Map.Entry)) 14 return false; 15 Map.Entry<?,?> e = (Map.Entry<?,?>) o; 16 Object key = e.getKey(); 17 Node<K,V> candidate = getNode(hash(key), key); 18 return candidate != null && candidate.equals(e); 19 } 20 public final boolean remove(Object o) { 21 if (o instanceof Map.Entry) { 22 Map.Entry<?,?> e = (Map.Entry<?,?>) o; 23 Object key = e.getKey(); 24 Object value = e.getValue(); 25 return removeNode(hash(key), key, value, true, true) != null; 26 } 27 return false; 28 } 29 public final Spliterator<Map.Entry<K,V>> spliterator() { 30 return new EntrySpliterator<>(HashMap.this, 0, -1, 0, 0); 31 } 32 public final void forEach(Consumer<? super Map.Entry<K,V>> action) { 33 Node<K,V>[] tab; 34 if (action == null) 35 throw new NullPointerException(); 36 if (size > 0 && (tab = table) != null) { 37 int mc = modCount; 38 for (int i = 0; i < tab.length; ++i) { 39 for (Node<K,V> e = tab[i]; e != null; e = e.next) 40 action.accept(e); 41 } 42 if (modCount != mc) 43 throw new ConcurrentModificationException(); 44 } 45 } 46 }