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     }

 

posted @ 2023-03-09 00:21  童梦国度  阅读(11)  评论(0编辑  收藏  举报