/* ---------------- 字段中的默认值 -------------- */ /** * The default initial capacity - MUST be a power of two. * hashmap默认的初始化大小: 2的4次方,即16, */ staticfinalint DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
/** * The maximum capacity, used if a higher value is implicitly specified * by either of the constructors with arguments. * MUST be a power of two <= 1<<30. * hashmap最大容量:2的4次方 */ staticfinalint MAXIMUM_CAPACITY = 1 << 30;
/** * The load factor used when none specified in constructor. * hashmap默认的负载因子,默认0.75,即达到总容量的75%时,需要扩容 */ staticfinalfloat DEFAULT_LOAD_FACTOR = 0.75f;
/** * The bin count threshold for using a tree rather than list for a * bin. Bins are converted to trees when adding an element to a * bin with at least this many nodes. The value must be greater * than 2 and should be at least 8 to mesh with assumptions in * tree removal about conversion back to plain bins upon * shrinkage. * 转化树形结构的阈值,默认8,即当某个链表上的节点长度大于8时,将这 * 个链表转化为红黑树 */ staticfinalint TREEIFY_THRESHOLD = 8;
/** * The bin count threshold for untreeifying a (split) bin during a * resize operation. Should be less than TREEIFY_THRESHOLD, and at * most 6 to mesh with shrinkage detection under removal. * 从树形结构转化为单链表结构的阈值,默认6 */ staticfinalint UNTREEIFY_THRESHOLD = 6;
/** * The smallest table capacity for which bins may be treeified. * (Otherwise the table is resized if too many nodes in a bin.) * Should be at least 4 * TREEIFY_THRESHOLD to avoid conflicts * between resizing and treeification thresholds. * 对字段TREEIFY_THRESHOLD的一个补充,转化为红黑树的最小hashmap容量, * 如果某个链表的节点长度>8,但是总容量没达到64,hashmap会扩容,而不是 * 直接转化为红黑树。(自定义该值时,至少应为4 * TREEIFY_THRESHOLD以 * 避免在扩容还是转化为红黑树时产生冲突) */ staticfinalint MIN_TREEIFY_CAPACITY = 64; /* ---------------- Fields -------------- */
/** * The table, initialized on first use, and resized as * necessary. When allocated, length is always a power of two. * (We also tolerate length zero in some operations to allow * bootstrapping mechanics that are currently not needed.) * 存储链表元素的数组,初始化或者扩容的时候会用, */ transient Node<K,V>[] table;
/** * Holds cached entrySet(). Note that AbstractMap fields are used * for keySet() and values(). * 具体的几点数据集合, */ transient Set<Map.Entry<K,V>> entrySet;
/** * The number of key-value mappings contained in this map. * hashmap总节点的个数,即容量 */ transientint size;
/** * The number of times this HashMap has been structurally modified * Structural modifications are those that change the number of mappings in * the HashMap or otherwise modify its internal structure (e.g., * rehash). This field is used to make iterators on Collection-views of * the HashMap fail-fast. (See ConcurrentModificationException). * 记录hashmap被修改的次数,包括rehash,添加数据等,在遍历数据时可以起到快速 * 失败的作用 */ transientint modCount;
/** * The next size value at which to resize (capacity * load factor). * 下一次扩容的阈值,capacity * load factor * @serial */ // (The javadoc description is true upon serialization. // Additionally, if the table array has not been allocated, this // field holds the initial array capacity, or zero signifying // DEFAULT_INITIAL_CAPACITY.) int threshold;
/** * The load factor for the hash table. * 负载因子 * @serial */ finalfloat loadFactor;
/** * Removes the mapping for the specified key from this map if present. * * @param key key whose mapping is to be removed from the map * @return the previous value associated with <tt>key</tt>, or * <tt>null</tt> if there was no mapping for <tt>key</tt>. * (A <tt>null</tt> return can also indicate that the map * previously associated <tt>null</tt> with <tt>key</tt>.) */ public V remove(Object key){ Node<K,V> e; return (e = removeNode(hash(key), key, null, false, true)) == null ? null : e.value; }
/** * Implements Map.remove and related methods * * @param hash hash for key * @param key the key * @param value the value to match if matchValue, else ignored * @param matchValue if true only remove if value is equal * @param movable if false do not move other nodes while removing * @return the node, or null if none */ final Node<K,V> removeNode(int hash, Object key, Object value, boolean matchValue, boolean movable){ Node<K,V>[] tab; Node<K,V> p; int n, index; //前提:table里面有数据,并且找到的桶位的头结点不为null if ((tab = table) != null && (n = tab.length) > 0 && (p = tab[index = (n - 1) & hash]) != null) { Node<K,V> node = null, e; K k; V v; //1.找到要删除的节点 //1.1 头结点就是 if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k)))) node = p; //1.2 头结点不是,获取下一个节点 elseif ((e = p.next) != null) { // 1.2.1 数据结构是红黑树,按红黑树的方式查找 if (p instanceof TreeNode) node = ((TreeNode<K,V>)p).getTreeNode(hash, key); // 1.2.2 数据结构是链表,按链表的方式查找 else { do { if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) { node = e; break; } p = e; } while ((e = e.next) != null); } } // 2. 找到要删除的节点 if (node != null && (!matchValue || (v = node.value) == value || (value != null && value.equals(v)))) { // 2.1 找到的节点是红黑数结构,按红黑树方式删除 if (node instanceof TreeNode) ((TreeNode<K,V>)node).removeTreeNode(this, tab, movable); // 2.2 找到的节点是链表 //2.2.1 是头结点 elseif (node == p) tab[index] = node.next; // 2.2.2 不是头结点 else p.next = node.next; // 修改次数加1,size减1,返回删除的节点 ++modCount; --size; afterNodeRemoval(node); return node; } } returnnull; }