HashMap注释翻译

package java.util;import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;import sun.misc.SharedSecrets;/**基于哈希表实现的映射接口。这*实现提供了所有可选的map操作和许可证*空值和空键。(HashMapclass大致相当于Hashtable,除了它是这个类不做任何保证*map的次序;特别是,它不能保证订单会随着时间保持不变。**这个实现为basic提供了常量时间性能*操作(get和put),假设是哈希函数*将元素适当地分散到各个桶中。迭代*收集视图所需时间与“容量”成正比HashMap实例(桶的数量)加上它的大小(桶的数量)*键值映射)。因此,不要设置初始值是非常重要的*如果迭代性能过高(或负载因子过低)*重要。**HashMap的实例有两个参数,这两个参数影响它*性能:初始容量和负载系数。的*容量是哈希表中的桶数和初始桶数*容量就是创建哈希表时的容量。的*加载因子是对允许哈希表的满度的度量*在它的容量自动增加之前。当*哈希表中的项超过了负载因子和的乘积*当前容量,哈希表被重新哈希(即内部数据)*结构被重建),使哈希表大约有两倍的桶的数量。**作为一个通用规则,默认的负载因子(.75)提供了一个良好的性能*权衡时间和空间成本。值越高,*空间开销,但增加查找成本(反映在大多数HashMap类的操作,包括*获取和放置)。所期望的项数*地图及其负载因素应考虑时*设置其初始容量,使*重复操作。如果初始容量大于*最大条目数除以负载因子,没有重哈希*操作永远不会发生。**如果要在HashMap中存储许多映射例如,创建一个足够大的容量将允许*映射将被更有效地存储,而不是让它执行*根据需要自动重新哈希表。注意,使用*许多带有相同{@code hashCode()}的键肯定会减慢速度*降低任何哈希表的性能。改善影响,当关键* are {@link Comparable},这个类可以使用之间的比较顺序*帮助打破关系的钥匙。**注意,这个实现不是同步的。*如果多个线程同时访问一个散列映射,且至少一个*线程修改映射的结构,它必须*外部同步。结构修改是指任何操作*添加或删除一个或多个映射;只是改变了值*与实例已包含的键关联的不是这通常是由同步一些对象,自然封装映射。**如果不存在此类对象,则应使用* {@link Collections#synchronizedMap Collections.synchronizedMap}*方法。这最好在创建时完成,以防止意外*对地图的不同步访问:* Map m =集合。synchronizedMap(新HashMap (…));**这个类的所有“集合视图方法”返回的迭代器*是故障-快速:如果地图是结构性修改后的任何时间迭代器被创建,除了通过迭代器自己的方式*删除方法,迭代器将抛出一个* {@link ConcurrentModificationException}。因此,面对并发*修改时,迭代器会快速而干净地失败,而不会有风险的任意、不确定的行为*未来。**注意,不能保证迭代器的快速故障行为一般来说,我们不可能做出任何严格的保证*存在不同步的并发修改。快速失败迭代器*尽最大努力抛出ConcurrentModificationException。因此,写一个依赖于此的程序是错误的*异常的正确性:迭代器的快速失效行为*应该只用于检测bug。**这个类是** Java集合框架。* *** @param <K> the type of keys maintained by this map* @param <V> the type of mapped values** @author  Doug Lea* @author  Josh Bloch* @author  Arthur van Hoff* @author  Neal Gafter* @see     Object#hashCode()* @see     Collection* @see     Map* @see     TreeMap* @see     Hashtable* @since   1.2*/
public class HashMap<K, V> extends AbstractMap<K, V>implements Map<K, V>, Cloneable, Serializable {private static final long serialVersionUID = 362498820763181265L;/* 实现说明。**这个映射通常充当一个被绑定(被屏蔽)的哈希表,但是*当箱子变得太大时,它们会被转换成*树节点,每个节点的结构类似于* java.util.TreeMap。大多数方法尝试使用普通的箱子,但是*在适用时转发到TreeNode方法(只需检查)*节点的instanceof)。可以遍历和*像其他的一样使用,但是另外支持更快的查找*当人口过剩。然而,由于绝大多数的垃圾箱*正常使用不超载,检查是否存在*在表方法的过程中,可能会延迟树容器。**树箱(即元素都是树节点的箱子)*主要根据hashCode排序,但如果是tie,则是两个*元素属于相同的“C类实现可比较”,*类型,然后他们的compareTo方法用于排序。(我们*通过反射保守地检查泛型类型以进行验证* this——参见方法comparableClassFor)。增加了复杂性*提供最坏情况O(log n)是值得的*当键具有不同的哈希值或为时的操作*可排序,因此,性能优雅地下降*hashCode()方法的意外或恶意使用*返回的值分布不均匀,以及*许多密钥共享一个hashCode,只要它们也是*具有可比性。如果这两个都不适用,我们可能会浪费a*在时间和空间上的因素是2,而不是*预防措施。但目前所知的案例都来自于糟糕的用户*编程实践已经如此缓慢,这使得*小区别。)**因为树节点的大小是普通节点的两倍*只有当箱子中有足够的节点时才使用*(见TREEIFY_THRESHOLD)。当它们变得太小的时候(由于*删除或调整大小)它们被转换回普通的垃圾箱。在*使用分布良好的用户哈希码,树箱是*很少使用。理想情况下,在随机哈希码下*bin中的节点服从泊松分布*(http://en.wikipedia.org/wiki/Poisson_distribution)*默认大小调整的平均参数约为0.5*阈值为0.75,虽然有较大的方差,因为*调整粒度。忽略方差,得到期望*列表大小k的出现次数为(exp(-0.5) * pow(0.5, k) /* factorial (k))。第一个值是:** 0:0.60653066* 1:0.30326533* 2:0.07581633* 3:0.01263606* 4:0.00157952* 5:0.00015795* 6:0.00001316* 7:0.00000094* 8:0.00000006*更多:少于千万分之一**树状容器的根通常是它的第一个节点。然而,*有时(当前仅针对Iterator.remove),根可能*在其他地方,但可以通过父链接恢复* (TreeNode.root()方法)。**所有适用的内部方法都接受哈希码作为*参数(通常由公共方法提供),允许*在不重新计算用户哈希码的情况下调用。*也就是说,大多数内部方法也接受“tab”参数*通常是当前表,但可能是新表或旧表时*调整大小或转换。**当bin列表被treeified、split或untreeified时,我们保留*它们以相同的相对存取/遍历次序(即、现场*(下同)为了更好地保存局部,对*简化对调用的分割和遍历的处理* iterator.remove。当使用比较器进行插入时,要保持a*总排序(或相近的是需要在这里)* rebalancings,我们将类和identityHashCodes进行比较*参加。**普通vs树模式之间的使用和转换是*由于LinkedHashMap子类的存在而变得复杂。看到*下面是定义在插入时调用的钩子方法,*删除和访问允许LinkedHashMap内部*否则保持独立于这些机制。(这也*要求将映射实例传递给一些实用程序方法*可能会创建新节点。)**基于ssa的并行编程风格很有帮助*避免所有扭曲指针操作中的别名错误。*//*** 默认的初始容量-必须是2的幂。*/static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16/*** 如果隐式指定了更高的值,则使用最大容量* 由任何一个带参数的构造函数。* 必须是2的幂<= 1<<30。*/static final int MAXIMUM_CAPACITY = 1 << 30;/*** 在构造函数中没有指定时使用的负载因子*/static final float DEFAULT_LOAD_FACTOR = 0.75f;/*** 使用树而不是列表的bin计数阈值* 本。在向a中添加元素时,箱子被转换为树* 至少有这么多节点的bin。值必须更大* 大于2,且应至少为8,以配合假设* 关于转换回普通箱的树移除* 收缩。*/static final int TREEIFY_THRESHOLD = 8;/*** 在a期间取消对一个(拆分的)bin进行树化的bin计数阈值* 调整操作。是否小于TREEIFY_THRESHOLD,at* 大部分6到网格与删除收缩检测。*/static final int UNTREEIFY_THRESHOLD = 6;/*** 最小的可存放箱子的桌子容量。* (否则,如果一个bin中有太多节点,就会重新调整表的大小。)* 应至少达到4 * TREEIFY_THRESHOLD以避免冲突* 在调整大小和treeification阈值之间。*/static final int MIN_TREEIFY_CAPACITY = 64;/*** 基本的哈希bin节点,用于大多数条目。(见下文* TreeNode子类,其条目子类在LinkedHashMap中。)*/static class Node<K, V> implements Map.Entry<K, V> {final int hash;final K key;V value;Node<K, V> next;Node(int hash, K key, V value, Node<K, V> next) {this.hash = hash;this.key = key;this.value = value;this.next = next;}public final K getKey() {return key;}public final V getValue() {return value;}public final String toString() {return key + "=" + value;}public final int hashCode() {return Objects.hashCode(key) ^ Objects.hashCode(value);}public final V setValue(V newValue) {V oldValue = value;value = newValue;return oldValue;}public final boolean equals(Object o) {if (o == this)return true;if (o instanceof Map.Entry) {Map.Entry<?, ?> e = (Map.Entry<?, ?>) o;if (Objects.equals(key, e.getKey()) &&Objects.equals(value, e.getValue()))return true;}return false;}}/* ---------------- 静态的公用事业 -------------- *//*** 计算key.hashCode()并扩展(XORs)更高的散列位* 低。因为表使用了2的幂的掩蔽,所以集合* 仅在当前掩码上的位上变化的散列会* 总是碰撞。(已知的例子包括一组浮点键* 在小表格中保存连续的整数)所以我们* 应用一个变换来分散高比特的影响* 向下。在速度、效用和之间有一个权衡* 点播质量。因为有很多常见的哈希值* 已经合理分布(所以不要从中受益* 因为我们用树木来处理大量的树木* 碰撞在箱子里,我们只是XOR一些移位的位* 最便宜的方法来减少系统的损失,以及* 合并最高位的影响,否则* 不要在索引计算中使用,因为表的边界。*/static final int hash(Object key) {int h;return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);}/*** 返回x的类,如果它是“C类实现”的形式* Comparable<C>",否则为空。*/static Class<?> comparableClassFor(Object x) {if (x instanceof Comparable) {Class<?> c;Type[] ts, as;Type t;ParameterizedType p;if ((c = x.getClass()) == String.class) // bypass checksreturn c;if ((ts = c.getGenericInterfaces()) != null) {for (int i = 0; i < ts.length; ++i) {if (((t = ts[i]) instanceof ParameterizedType) &&((p = (ParameterizedType) t).getRawType() ==Comparable.class) &&(as = p.getActualTypeArguments()) != null &&as.length == 1 && as[0] == c) // type arg is creturn c;}}}return null;}/*** 返回k.compareto(x)* <p>* 如果x匹配kc(k的屏幕可比* class),否则0。*/@SuppressWarnings({"rawtypes", "unchecked"}) // for cast to Comparablestatic int compareComparables(Class<?> kc, Object k, Object x) {return (x == null || x.getClass() != kc ? 0 :((Comparable) k).compareTo(x));}/*** 返回给定目标容量的两倍幂。*/static final int tableSizeFor(int cap) {int n = cap - 1;n |= n >>> 1;n |= n >>> 2;n |= n >>> 4;n |= n >>> 8;n |= n >>> 16;return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;}/* ---------------- Fields -------------- *//*** 表,第一次使用时初始化,并调整大小为* 必要的。当分配时,长度总是2的幂。* (我们也容忍长度为零的一些操作允许* 目前不需要的引导机制。)*/transient Node<K, V>[] table;/*** 保存缓存的entrySet()。注意使用了AbstractMap字段* 用于keySet()和values()。*/transient Set<Map.Entry<K, V>> entrySet;/*** 此映射中包含的键值映射的数量。*/transient int size;/*** 此HashMap在结构上修改的次数* 结构修改是指改变映射的数量* HashMap或以其他方式修改其内部结构(例如,* 重复)。此字段用于对集合视图生成迭代器* HashMap失败得很快。(见ConcurrentModificationException)。*/transient int modCount;/*** 要调整大小的下一个大小值(容量*负载因子)。** @serial*///(序列化后,javadoc描述为true。
//另外,如果还没有分配表数组,则执行以下操作
//字段持有初始数组容量,或表示为零
// DEFAULT_INITIAL_CAPACITY)。int threshold;/*** 哈希表的加载因子。** @serial*/final float loadFactor;/* ---------------- Public operations -------------- *//***使用指定的初始值构造一个空的<tt>HashMap</tt>*容量和负载因素。*初始容量* @param加载因子加载因子如果初始容量为负,则抛出IllegalArgumentException或者负载因子是非正的*/public HashMap(int initialCapacity, float loadFactor) {if (initialCapacity < 0)throw new IllegalArgumentException("Illegal initial capacity: " +initialCapacity);if (initialCapacity > MAXIMUM_CAPACITY)initialCapacity = MAXIMUM_CAPACITY;if (loadFactor <= 0 || Float.isNaN(loadFactor))throw new IllegalArgumentException("Illegal load factor: " +loadFactor);this.loadFactor = loadFactor;this.threshold = tableSizeFor(initialCapacity);}/*** 使用指定的初始值构造一个空的<tt>HashMap</tt>* 容量和默认负载因子(0.75)。* <p>* 初始容量。* 如果初始容量为负,则抛出IllegalArgumentException。*/public HashMap(int initialCapacity) {this(initialCapacity, DEFAULT_LOAD_FACTOR);}/*** 使用默认初始容量构造一个空的<tt>HashMap</tt>* (16)和默认的负载因子(0.75)。*/public HashMap() {this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted}/*** 使用与. .相同的映射构造新的HashMap* 指定地图。HashMap是用* 默认负载因数(0.75)和足够的初始容量* 保存指定映射中的映射。** @param m 映射将被放置在这个映射中的映射*          如果指定的映射为空,@抛出NullPointerException*/public HashMap(Map<? extends K, ? extends V> m) {this.loadFactor = DEFAULT_LOAD_FACTOR;putMapEntries(m, false);}/*** 实现地图。putAll和Map构造函数** @param m地图* @param在最初构建此地图时为false,否则 为真(转发到下午插入方法)。*/final void putMapEntries(Map<? extends K, ? extends V> m, boolean evict) {int s = m.size();if (s > 0) {if (table == null) { // pre-sizefloat ft = ((float) s / loadFactor) + 1.0F;int t = ((ft < (float) MAXIMUM_CAPACITY) ?(int) ft : MAXIMUM_CAPACITY);if (t > threshold)threshold = tableSizeFor(t);} else if (s > threshold)resize();for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) {K key = e.getKey();V value = e.getValue();putVal(hash(key), key, value, false, evict);}}}/*** Returns the number of key-value mappings in this map.** @return the number of key-value mappings in this map*/public int size() {return size;}/*** Returns <tt>true</tt> if this map contains no key-value mappings.** @return <tt>true</tt> if this map contains no key-value mappings*/public boolean isEmpty() {return size == 0;}/*** 返回指定键映射到的值,* 或{@code null},如果此映射不包含键的映射。** <p>更正式,如果这个映射包含一个键的映射* {@code k}到一个值{@code v},使得{@code (key==null ?k = =零:* key.equals(k))},则该方法返回{@code v};否则* 它返回{@code null}。(最多可以有一个这样的映射。)* <p>* {@code null}的返回值不一定<i> </i>* 表示该映射不包含键的映射;这也是* 可能映射显式地将键映射到{@code null}。* {@link #containsKey}操作可用于* 区分这两种情况。** @see #put (对象,对象)*/public V get(Object key) {Node<K, V> e;return (e = getNode(hash(key), key)) == null ? null : e.value;}/*** 实现地图。get和相关方法** @param hash for key* @param密钥* @返回节点,如果没有则返回null*/final Node<K, V> getNode(int hash, Object key) {Node<K, V>[] tab;Node<K, V> first, e;int n;K k;if ((tab = table) != null && (n = tab.length) > 0 &&(first = tab[(n - 1) & hash]) != null) {if (first.hash == hash && // always check first node((k = first.key) == key || (key != null && key.equals(k))))return first;if ((e = first.next) != null) {if (first instanceof TreeNode)return ((TreeNode<K, V>) first).getTreeNode(hash, key);do {if (e.hash == hash &&((k = e.key) == key || (key != null && key.equals(k))))return e;} while ((e = e.next) != null);}}return null;}/*** 如果此映射包含* 指定的关键。** @return true如果这个映射包含指定的映射* 键。* @param键该键在此地图中的存在将被测试*/public boolean containsKey(Object key) {return getNode(hash(key), key) != null;}/*** 将指定值与此映射中的指定键关联。* 如果之前的映射包含一个键的映射,则为旧的* 值被替换。** @param键是与指定值相关联的键* @param值与指定的键相关联的值* @返回与键或关联的前一个值 null,如果没有映射键。* (一个空返回也可以表示映射* 先前将null与键关联。)*/public V put(K key, V value) {return putVal(hash(key), key, value, false, true);}/*** 实现地图。put及相关方法** @param hash         for key* @param onlyIfAbsent 如果为真,不要更改现有值* @param密钥* @param值* @param如果为false,则该表处于创建模式。* @返回以前的值,如果没有则返回null*/final V putVal(int hash, K key, V value, boolean onlyIfAbsent,boolean evict) {Node<K, V>[] tab;Node<K, V> p;int n, i;if ((tab = table) == null || (n = tab.length) == 0)n = (tab = resize()).length;if ((p = tab[i = (n - 1) & hash]) == null)tab[i] = newNode(hash, key, value, null);else {Node<K, V> e;K k;if (p.hash == hash &&((k = p.key) == key || (key != null && key.equals(k))))e = p;else if (p instanceof TreeNode)e = ((TreeNode<K, V>) p).putTreeVal(this, tab, hash, key, value);else {for (int binCount = 0; ; ++binCount) {if ((e = p.next) == null) {p.next = newNode(hash, key, value, null);if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1sttreeifyBin(tab, hash);break;}if (e.hash == hash &&((k = e.key) == key || (key != null && key.equals(k))))break;p = e;}}if (e != null) { // existing mapping for keyV oldValue = e.value;if (!onlyIfAbsent || oldValue == null)e.value = value;afterNodeAccess(e);return oldValue;}}++modCount;if (++size > threshold)resize();afterNodeInsertion(evict);return null;}/*** 初始化或加倍表大小。如果为空,则分配in* 符合田间阈值设定的初始产能目标。* 否则,因为我们使用的是2的幂次展开式* 每个bin中的元素必须保持相同的索引,或者移动* 新表中的偏移量为2的幂。** @返回表*/final Node<K, V>[] resize() {Node<K, V>[] oldTab = table;int oldCap = (oldTab == null) ? 0 : oldTab.length;int oldThr = threshold;int newCap, newThr = 0;if (oldCap > 0) {if (oldCap >= MAXIMUM_CAPACITY) {threshold = Integer.MAX_VALUE;return oldTab;} else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&oldCap >= DEFAULT_INITIAL_CAPACITY)newThr = oldThr << 1; // double threshold双阈值} else if (oldThr > 0) // initial capacity was placed in threshold初始容量设置为阈值newCap = oldThr;else {               // 初始阈值为零表示使用默认值newCap = DEFAULT_INITIAL_CAPACITY;newThr = (int) (DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);}if (newThr == 0) {float ft = (float) newCap * loadFactor;newThr = (newCap < MAXIMUM_CAPACITY && ft < (float) MAXIMUM_CAPACITY ?(int) ft : Integer.MAX_VALUE);}threshold = newThr;@SuppressWarnings({"rawtypes", "unchecked"})Node<K, V>[] newTab = (Node<K, V>[]) new Node[newCap];table = newTab;if (oldTab != null) {for (int j = 0; j < oldCap; ++j) {Node<K, V> e;if ((e = oldTab[j]) != null) {oldTab[j] = null;if (e.next == null)newTab[e.hash & (newCap - 1)] = e;else if (e instanceof TreeNode)((TreeNode<K, V>) e).split(this, newTab, j, oldCap);else { // preserve orderNode<K, V> loHead = null, loTail = null;Node<K, V> hiHead = null, hiTail = null;Node<K, V> next;do {next = e.next;if ((e.hash & oldCap) == 0) {if (loTail == null)loHead = e;elseloTail.next = e;loTail = e;} else {if (hiTail == null)hiHead = e;elsehiTail.next = e;hiTail = e;}} while ((e = next) != null);if (loTail != null) {loTail.next = null;newTab[j] = loHead;}if (hiTail != null) {hiTail.next = null;newTab[j + oldCap] = hiHead;}}}}}return newTab;}/*** 替换所有链接节点在bin的索引为给定的哈希除非* 表格太小,在这种情况下会改变大小。*/final void treeifyBin(Node<K, V>[] tab, int hash) {int n, index;Node<K, V> e;if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY)resize();else if ((e = tab[index = (n - 1) & hash]) != null) {TreeNode<K, V> hd = null, tl = null;do {TreeNode<K, V> p = replacementTreeNode(e, null);if (tl == null)hd = p;else {p.prev = tl;tl.next = p;}tl = p;} while ((e = e.next) != null);if ((tab[index] = hd) != null)hd.treeify(tab);}}/*** 将指定映射的所有映射复制到此映射。* 这些映射将替换此映射的所有映射* 当前在指定映射中的任何键。** @param m 映射将存储在这个映射中*          如果指定的映射为空,@抛出NullPointerException*/public void putAll(Map<? extends K, ? extends V> m) {putMapEntries(m, true);}/*** 如果存在,则从该映射中删除指定键的映射。** @param密钥,其映射将从映射中删除* @返回与键或关联的前一个值 null,如果没有映射键。* (一个空返回也可以表示映射* 先前将null与键关联。)*/public V remove(Object key) {Node<K, V> e;return (e = removeNode(hash(key), key, null, false, true)) == null ?null : e.value;}/*** 实现地图。删除和相关方法** @param hash                     for key* @param matchValue(如果为真)只在值相等时移除* @param matchValue,在删除时不移动其他节点* @param密钥* @param值如果匹配值,则忽略* @返回节点,如果没有则返回null*/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;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;if (p.hash == hash &&((k = p.key) == key || (key != null && key.equals(k))))node = p;else if ((e = p.next) != null) {if (p instanceof TreeNode)node = ((TreeNode<K, V>) p).getTreeNode(hash, key);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);}}if (node != null && (!matchValue || (v = node.value) == value ||(value != null && value.equals(v)))) {if (node instanceof TreeNode)((TreeNode<K, V>) node).removeTreeNode(this, tab, movable);else if (node == p)tab[index] = node.next;elsep.next = node.next;++modCount;--size;afterNodeRemoval(node);return node;}}return null;}/*** 从该映射中删除所有映射。* 调用返回后映射将为空。*/public void clear() {Node<K, V>[] tab;modCount++;if ((tab = table) != null && size > 0) {size = 0;for (int i = 0; i < tab.length; ++i)tab[i] = null;}}/*** 如果此映射将一个或多个键映射到。则返回<tt>true</tt>* 指定值。** @return <tt>true</tt>如果此映射将一个或多个键映射到* 指定值* @param值,该值在此映射中的存在将被测试*/public boolean containsValue(Object value) {Node<K, V>[] tab;V v;if ((tab = table) != null && size > 0) {for (int i = 0; i < tab.length; ++i) {for (Node<K, V> e = tab[i]; e != null; e = e.next) {if ((v = e.value) == value ||(value != null && value.equals(v)))return true;}}}return false;}/*** 返回包含在此映射中的键的{@link Set}视图。* set是由map支持的,所以对map的更改是* 反映在集合中,反之亦然。如果地图被修改* 对集合的迭代正在进行中(除了through)* 迭代器自身的删除操作)的结果* 迭代没有定义。集合支持元素移除,* 方法从映射中删除对应的映射* 迭代器。删除Set.remove,* 移除所有,保持所有,清除* 操作。它不支持添加或添加* 操作。** @返回此映射中包含的键的集合视图*/public Set<K> keySet() {Set<K> ks = keySet;if (ks == null) {ks = new KeySet();keySet = ks;}return ks;}final class KeySet extends AbstractSet<K> {public final int size() {return size;}public final void clear() {HashMap.this.clear();}public final Iterator<K> iterator() {return new KeyIterator();}public final boolean contains(Object o) {return containsKey(o);}public final boolean remove(Object key) {return removeNode(hash(key), key, null, false, true) != null;}public final Spliterator<K> spliterator() {return new KeySpliterator<>(HashMap.this, 0, -1, 0, 0);}public final void forEach(Consumer<? super K> action) {Node<K, V>[] tab;if (action == null)throw new NullPointerException();if (size > 0 && (tab = table) != null) {int mc = modCount;for (int i = 0; i < tab.length; ++i) {for (Node<K, V> e = tab[i]; e != null; e = e.next)action.accept(e.key);}if (modCount != mc)throw new ConcurrentModificationException();}}}/*** 返回包含在此映射中的值的{@link Collection}视图。* 集合由映射支持,所以对映射的更改是* 反映在集合中,反之亦然。如果地图是* 在对集合进行迭代时进行修改* (除非通过迭代器自己的删除操作),* 迭代的结果是未定义的。集合* 支持元素移除,移除对应的元素* 通过迭代器从映射映射,* 收集。删除removeAll,* 保持和清除操作。它不* 支持添加或添加所有操作。** @返回此映射中包含的值的视图*/public Collection<V> values() {Collection<V> vs = values;if (vs == null) {vs = new Values();values = vs;}return vs;}final class Values extends AbstractCollection<V> {public final int size() {return size;}public final void clear() {HashMap.this.clear();}public final Iterator<V> iterator() {return new ValueIterator();}public final boolean contains(Object o) {return containsValue(o);}public final Spliterator<V> spliterator() {return new ValueSpliterator<>(HashMap.this, 0, -1, 0, 0);}public final void forEach(Consumer<? super V> action) {Node<K, V>[] tab;if (action == null)throw new NullPointerException();if (size > 0 && (tab = table) != null) {int mc = modCount;for (int i = 0; i < tab.length; ++i) {for (Node<K, V> e = tab[i]; e != null; e = e.next)action.accept(e.value);}if (modCount != mc)throw new ConcurrentModificationException();}}}/*** 返回包含在这个映射中的{@link Set}视图。* set是由map支持的,所以对map的更改是* 反映在集合中,反之亦然。如果地图被修改* 对集合的迭代正在进行中(除了through)* 迭代器自己的删除操作,或通过* 方法返回的映射项上的setValue操作* 迭代的结果是未定义的。一组* 支持元素移除,移除对应的元素* 通过迭代器从映射映射,* Set.remove, removeAll, retainAll and* 明确操作。它不支持* 添加或添加所有操作。** @返回该映射中包含的映射的集合视图*/public Set<Map.Entry<K, V>> entrySet() {Set<Map.Entry<K, V>> es;return (es = entrySet) == null ? (entrySet = new EntrySet()) : es;}final class EntrySet extends AbstractSet<Map.Entry<K, V>> {public final int size() {return size;}public final void clear() {HashMap.this.clear();}public final Iterator<Map.Entry<K, V>> iterator() {return new EntryIterator();}public final boolean contains(Object o) {if (!(o instanceof Map.Entry))return false;Map.Entry<?, ?> e = (Map.Entry<?, ?>) o;Object key = e.getKey();Node<K, V> candidate = getNode(hash(key), key);return candidate != null && candidate.equals(e);}public final boolean remove(Object o) {if (o instanceof Map.Entry) {Map.Entry<?, ?> e = (Map.Entry<?, ?>) o;Object key = e.getKey();Object value = e.getValue();return removeNode(hash(key), key, value, true, true) != null;}return false;}public final Spliterator<Map.Entry<K, V>> spliterator() {return new EntrySpliterator<>(HashMap.this, 0, -1, 0, 0);}public final void forEach(Consumer<? super Map.Entry<K, V>> action) {Node<K, V>[] tab;if (action == null)throw new NullPointerException();if (size > 0 && (tab = table) != null) {int mc = modCount;for (int i = 0; i < tab.length; ++i) {for (Node<K, V> e = tab[i]; e != null; e = e.next)action.accept(e);}if (modCount != mc)throw new ConcurrentModificationException();}}}// Overrides of JDK8 Map extension methods@Overridepublic V getOrDefault(Object key, V defaultValue) {Node<K, V> e;return (e = getNode(hash(key), key)) == null ? defaultValue : e.value;}@Overridepublic V putIfAbsent(K key, V value) {return putVal(hash(key), key, value, true, true);}@Overridepublic boolean remove(Object key, Object value) {return removeNode(hash(key), key, value, true, true) != null;}@Overridepublic boolean replace(K key, V oldValue, V newValue) {Node<K, V> e;V v;if ((e = getNode(hash(key), key)) != null &&((v = e.value) == oldValue || (v != null && v.equals(oldValue)))) {e.value = newValue;afterNodeAccess(e);return true;}return false;}@Overridepublic V replace(K key, V value) {Node<K, V> e;if ((e = getNode(hash(key), key)) != null) {V oldValue = e.value;e.value = value;afterNodeAccess(e);return oldValue;}return null;}@Overridepublic V computeIfAbsent(K key,Function<? super K, ? extends V> mappingFunction) {if (mappingFunction == null)throw new NullPointerException();int hash = hash(key);Node<K, V>[] tab;Node<K, V> first;int n, i;int binCount = 0;TreeNode<K, V> t = null;Node<K, V> old = null;if (size > threshold || (tab = table) == null ||(n = tab.length) == 0)n = (tab = resize()).length;if ((first = tab[i = (n - 1) & hash]) != null) {if (first instanceof TreeNode)old = (t = (TreeNode<K, V>) first).getTreeNode(hash, key);else {Node<K, V> e = first;K k;do {if (e.hash == hash &&((k = e.key) == key || (key != null && key.equals(k)))) {old = e;break;}++binCount;} while ((e = e.next) != null);}V oldValue;if (old != null && (oldValue = old.value) != null) {afterNodeAccess(old);return oldValue;}}V v = mappingFunction.apply(key);if (v == null) {return null;} else if (old != null) {old.value = v;afterNodeAccess(old);return v;} else if (t != null)t.putTreeVal(this, tab, hash, key, v);else {tab[i] = newNode(hash, key, v, first);if (binCount >= TREEIFY_THRESHOLD - 1)treeifyBin(tab, hash);}++modCount;++size;afterNodeInsertion(true);return v;}public V computeIfPresent(K key,BiFunction<? super K, ? super V, ? extends V> remappingFunction) {if (remappingFunction == null)throw new NullPointerException();Node<K, V> e;V oldValue;int hash = hash(key);if ((e = getNode(hash, key)) != null &&(oldValue = e.value) != null) {V v = remappingFunction.apply(key, oldValue);if (v != null) {e.value = v;afterNodeAccess(e);return v;} elseremoveNode(hash, key, null, false, true);}return null;}@Overridepublic V compute(K key,BiFunction<? super K, ? super V, ? extends V> remappingFunction) {if (remappingFunction == null)throw new NullPointerException();int hash = hash(key);Node<K, V>[] tab;Node<K, V> first;int n, i;int binCount = 0;TreeNode<K, V> t = null;Node<K, V> old = null;if (size > threshold || (tab = table) == null ||(n = tab.length) == 0)n = (tab = resize()).length;if ((first = tab[i = (n - 1) & hash]) != null) {if (first instanceof TreeNode)old = (t = (TreeNode<K, V>) first).getTreeNode(hash, key);else {Node<K, V> e = first;K k;do {if (e.hash == hash &&((k = e.key) == key || (key != null && key.equals(k)))) {old = e;break;}++binCount;} while ((e = e.next) != null);}}V oldValue = (old == null) ? null : old.value;V v = remappingFunction.apply(key, oldValue);if (old != null) {if (v != null) {old.value = v;afterNodeAccess(old);} elseremoveNode(hash, key, null, false, true);} else if (v != null) {if (t != null)t.putTreeVal(this, tab, hash, key, v);else {tab[i] = newNode(hash, key, v, first);if (binCount >= TREEIFY_THRESHOLD - 1)treeifyBin(tab, hash);}++modCount;++size;afterNodeInsertion(true);}return v;}@Overridepublic V merge(K key, V value,BiFunction<? super V, ? super V, ? extends V> remappingFunction) {if (value == null)throw new NullPointerException();if (remappingFunction == null)throw new NullPointerException();int hash = hash(key);Node<K, V>[] tab;Node<K, V> first;int n, i;int binCount = 0;TreeNode<K, V> t = null;Node<K, V> old = null;if (size > threshold || (tab = table) == null ||(n = tab.length) == 0)n = (tab = resize()).length;if ((first = tab[i = (n - 1) & hash]) != null) {if (first instanceof TreeNode)old = (t = (TreeNode<K, V>) first).getTreeNode(hash, key);else {Node<K, V> e = first;K k;do {if (e.hash == hash &&((k = e.key) == key || (key != null && key.equals(k)))) {old = e;break;}++binCount;} while ((e = e.next) != null);}}if (old != null) {V v;if (old.value != null)v = remappingFunction.apply(old.value, value);elsev = value;if (v != null) {old.value = v;afterNodeAccess(old);} elseremoveNode(hash, key, null, false, true);return v;}if (value != null) {if (t != null)t.putTreeVal(this, tab, hash, key, value);else {tab[i] = newNode(hash, key, value, first);if (binCount >= TREEIFY_THRESHOLD - 1)treeifyBin(tab, hash);}++modCount;++size;afterNodeInsertion(true);}return value;}@Overridepublic void forEach(BiConsumer<? super K, ? super V> action) {Node<K, V>[] tab;if (action == null)throw new NullPointerException();if (size > 0 && (tab = table) != null) {int mc = modCount;for (int i = 0; i < tab.length; ++i) {for (Node<K, V> e = tab[i]; e != null; e = e.next)action.accept(e.key, e.value);}if (modCount != mc)throw new ConcurrentModificationException();}}@Overridepublic void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {Node<K, V>[] tab;if (function == null)throw new NullPointerException();if (size > 0 && (tab = table) != null) {int mc = modCount;for (int i = 0; i < tab.length; ++i) {for (Node<K, V> e = tab[i]; e != null; e = e.next) {e.value = function.apply(e.key, e.value);}}if (modCount != mc)throw new ConcurrentModificationException();}}/* ------------------------------------------------------------ */
//克隆和序列化/*** 返回此HashMap实例的浅拷贝:键和* 没有克隆值本身。** @返回此地图的浅拷贝*/@SuppressWarnings("unchecked")@Overridepublic Object clone() {HashMap<K, V> result;try {result = (HashMap<K, V>) super.clone();} catch (CloneNotSupportedException e) {// 这不应该发生,因为我们是可克隆的throw new InternalError(e);}result.reinitialize();result.putMapEntries(this, false);return result;}// 在序列化hashset时也使用这些方法final float loadFactor() {return loadFactor;}final int capacity() {return (table != null) ? table.length :(threshold > 0) ? threshold :DEFAULT_INITIAL_CAPACITY;}/*** 将HashMap实例的状态保存到流中(即,* 序列化)。* <p>* 的长度* bucket数组)被发送(int),后面跟着* size (int,键值的数量)* 映射),然后是键(对象)和值(对象)* 用于每个键值映射。键值映射是* 无特定顺序发出。*/private void writeObject(java.io.ObjectOutputStream s)throws IOException {int buckets = capacity();// 写出阈值、loadfactor和任何隐藏的东西s.defaultWriteObject();s.writeInt(buckets);s.writeInt(size);internalWriteEntries(s);}/*** 从一个流(即,* 反序列化)。*/private void readObject(java.io.ObjectInputStream s)throws IOException, ClassNotFoundException {// 读取阈值(忽略)、加载因子和任何隐藏内容s.defaultReadObject();reinitialize();if (loadFactor <= 0 || Float.isNaN(loadFactor))throw new InvalidObjectException("Illegal load factor: " +loadFactor);s.readInt();                // 读取并忽略桶的数量int mappings = s.readInt(); // 读取映射数量(大小)if (mappings < 0)throw new InvalidObjectException("Illegal mappings count: " +mappings);else if (mappings > 0) { // (if zero, use defaults)// 仅在内部使用给定的负载因子调整表的大小// range of 0.25...4.0float lf = Math.min(Math.max(0.25f, loadFactor), 4.0f);float fc = (float) mappings / lf + 1.0f;int cap = ((fc < DEFAULT_INITIAL_CAPACITY) ?DEFAULT_INITIAL_CAPACITY :(fc >= MAXIMUM_CAPACITY) ?MAXIMUM_CAPACITY :tableSizeFor((int) fc));float ft = (float) cap * lf;threshold = ((cap < MAXIMUM_CAPACITY && ft < MAXIMUM_CAPACITY) ?(int) ft : Integer.MAX_VALUE);//检查Map.Entry[].class,因为它是最近的公共类型
//我们正在创造的东西。SharedSecrets.getJavaOISAccess().checkArray(s, Map.Entry[].class, cap);@SuppressWarnings({"rawtypes", "unchecked"})Node<K, V>[] tab = (Node<K, V>[]) new Node[cap];table = tab;//读取键和值,并将映射放到HashMap中for (int i = 0; i < mappings; i++) {@SuppressWarnings("unchecked")K key = (K) s.readObject();@SuppressWarnings("unchecked")V value = (V) s.readObject();putVal(hash(key), key, value, false, false);}}}/* ------------------------------------------------------------ */// iteratorsabstract class HashIterator {Node<K, V> next;        // next entry to return下一项返回Node<K, V> current;     // current entry当前条目int expectedModCount;  // for fast-failint index;             // current slot 当前的位置HashIterator() {expectedModCount = modCount;Node<K, V>[] t = table;current = next = null;index = 0;if (t != null && size > 0) { // advance to first entry先入先出do {} while (index < t.length && (next = t[index++]) == null);}}public final boolean hasNext() {return next != null;}final Node<K, V> nextNode() {Node<K, V>[] t;Node<K, V> e = next;if (modCount != expectedModCount)throw new ConcurrentModificationException();if (e == null)throw new NoSuchElementException();if ((next = (current = e).next) == null && (t = table) != null) {do {} while (index < t.length && (next = t[index++]) == null);}return e;}public final void remove() {Node<K, V> p = current;if (p == null)throw new IllegalStateException();if (modCount != expectedModCount)throw new ConcurrentModificationException();current = null;K key = p.key;removeNode(hash(key), key, null, false, false);expectedModCount = modCount;}}final class KeyIterator extends HashIteratorimplements Iterator<K> {public final K next() {return nextNode().key;}}final class ValueIterator extends HashIteratorimplements Iterator<V> {public final V next() {return nextNode().value;}}final class EntryIterator extends HashIteratorimplements Iterator<Map.Entry<K, V>> {public final Map.Entry<K, V> next() {return nextNode();}}/* ------------------------------------------------------------ */// spliteratorsstatic class HashMapSpliterator<K, V> {final HashMap<K, V> map;Node<K, V> current;          // current nodeint index;                  // current index, modified on advance/split//当前索引,预先修改/分割int fence;                  // one past last indexint est;                    // size estimateint expectedModCount;       // for comodification checksHashMapSpliterator(HashMap<K, V> m, int origin,int fence, int est,int expectedModCount) {this.map = m;this.index = origin;this.fence = fence;this.est = est;this.expectedModCount = expectedModCount;}final int getFence() { // 在第一次使用时初始化栅栏和大小int hi;if ((hi = fence) < 0) {HashMap<K, V> m = map;est = m.size;expectedModCount = m.modCount;Node<K, V>[] tab = m.table;hi = fence = (tab == null) ? 0 : tab.length;}return hi;}public final long estimateSize() {getFence(); // force init力初始化return (long) est;}}static final class KeySpliterator<K, V>extends HashMapSpliterator<K, V>implements Spliterator<K> {KeySpliterator(HashMap<K, V> m, int origin, int fence, int est,int expectedModCount) {super(m, origin, fence, est, expectedModCount);}public KeySpliterator<K, V> trySplit() {int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;return (lo >= mid || current != null) ? null :new KeySpliterator<>(map, lo, index = mid, est >>>= 1,expectedModCount);}public void forEachRemaining(Consumer<? super K> action) {int i, hi, mc;if (action == null)throw new NullPointerException();HashMap<K, V> m = map;Node<K, V>[] tab = m.table;if ((hi = fence) < 0) {mc = expectedModCount = m.modCount;hi = fence = (tab == null) ? 0 : tab.length;} elsemc = expectedModCount;if (tab != null && tab.length >= hi &&(i = index) >= 0 && (i < (index = hi) || current != null)) {Node<K, V> p = current;current = null;do {if (p == null)p = tab[i++];else {action.accept(p.key);p = p.next;}} while (p != null || i < hi);if (m.modCount != mc)throw new ConcurrentModificationException();}}public boolean tryAdvance(Consumer<? super K> action) {int hi;if (action == null)throw new NullPointerException();Node<K, V>[] tab = map.table;if (tab != null && tab.length >= (hi = getFence()) && index >= 0) {while (current != null || index < hi) {if (current == null)current = tab[index++];else {K k = current.key;current = current.next;action.accept(k);if (map.modCount != expectedModCount)throw new ConcurrentModificationException();return true;}}}return false;}public int characteristics() {return (fence < 0 || est == map.size ? Spliterator.SIZED : 0) |Spliterator.DISTINCT;}}static final class ValueSpliterator<K, V>extends HashMapSpliterator<K, V>implements Spliterator<V> {ValueSpliterator(HashMap<K, V> m, int origin, int fence, int est,int expectedModCount) {super(m, origin, fence, est, expectedModCount);}public ValueSpliterator<K, V> trySplit() {int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;return (lo >= mid || current != null) ? null :new ValueSpliterator<>(map, lo, index = mid, est >>>= 1,expectedModCount);}public void forEachRemaining(Consumer<? super V> action) {int i, hi, mc;if (action == null)throw new NullPointerException();HashMap<K, V> m = map;Node<K, V>[] tab = m.table;if ((hi = fence) < 0) {mc = expectedModCount = m.modCount;hi = fence = (tab == null) ? 0 : tab.length;} elsemc = expectedModCount;if (tab != null && tab.length >= hi &&(i = index) >= 0 && (i < (index = hi) || current != null)) {Node<K, V> p = current;current = null;do {if (p == null)p = tab[i++];else {action.accept(p.value);p = p.next;}} while (p != null || i < hi);if (m.modCount != mc)throw new ConcurrentModificationException();}}public boolean tryAdvance(Consumer<? super V> action) {int hi;if (action == null)throw new NullPointerException();Node<K, V>[] tab = map.table;if (tab != null && tab.length >= (hi = getFence()) && index >= 0) {while (current != null || index < hi) {if (current == null)current = tab[index++];else {V v = current.value;current = current.next;action.accept(v);if (map.modCount != expectedModCount)throw new ConcurrentModificationException();return true;}}}return false;}public int characteristics() {return (fence < 0 || est == map.size ? Spliterator.SIZED : 0);}}static final class EntrySpliterator<K, V>extends HashMapSpliterator<K, V>implements Spliterator<Map.Entry<K, V>> {EntrySpliterator(HashMap<K, V> m, int origin, int fence, int est,int expectedModCount) {super(m, origin, fence, est, expectedModCount);}public EntrySpliterator<K, V> trySplit() {int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;return (lo >= mid || current != null) ? null :new EntrySpliterator<>(map, lo, index = mid, est >>>= 1,expectedModCount);}public void forEachRemaining(Consumer<? super Map.Entry<K, V>> action) {int i, hi, mc;if (action == null)throw new NullPointerException();HashMap<K, V> m = map;Node<K, V>[] tab = m.table;if ((hi = fence) < 0) {mc = expectedModCount = m.modCount;hi = fence = (tab == null) ? 0 : tab.length;} elsemc = expectedModCount;if (tab != null && tab.length >= hi &&(i = index) >= 0 && (i < (index = hi) || current != null)) {Node<K, V> p = current;current = null;do {if (p == null)p = tab[i++];else {action.accept(p);p = p.next;}} while (p != null || i < hi);if (m.modCount != mc)throw new ConcurrentModificationException();}}public boolean tryAdvance(Consumer<? super Map.Entry<K, V>> action) {int hi;if (action == null)throw new NullPointerException();Node<K, V>[] tab = map.table;if (tab != null && tab.length >= (hi = getFence()) && index >= 0) {while (current != null || index < hi) {if (current == null)current = tab[index++];else {Node<K, V> e = current;current = current.next;action.accept(e);if (map.modCount != expectedModCount)throw new ConcurrentModificationException();return true;}}}return false;}public int characteristics() {return (fence < 0 || est == map.size ? Spliterator.SIZED : 0) |Spliterator.DISTINCT;}}/* ------------------------------------------------------------ */// LinkedHashMap support/*** 下列包保护方法被设计为* 被LinkedHashMap覆盖,但不被任何其他子类覆盖。* 几乎所有其他内部方法都是包保护的* 但被声明为final,所以可以被LinkedHashMap, view使用* 类和HashSet。*/// Create a regular (non-tree) node创建一个常规(非树)节点Node<K, V> newNode(int hash, K key, V value, Node<K, V> next) {return new Node<>(hash, key, value, next);}// For conversion from TreeNodes to plain nodes用于从树节点到普通节点的转换Node<K, V> replacementNode(Node<K, V> p, Node<K, V> next) {return new Node<>(p.hash, p.key, p.value, next);}// Create a tree bin node创建一个树bin节点TreeNode<K, V> newTreeNode(int hash, K key, V value, Node<K, V> next) {return new TreeNode<>(hash, key, value, next);}// For treeifyBinTreeNode<K, V> replacementTreeNode(Node<K, V> p, Node<K, V> next) {return new TreeNode<>(p.hash, p.key, p.value, next);}/*** 重置为初始默认状态。通过克隆和readObject调用。* Reset to initial default state.  Called by clone and readObject.*/void reinitialize() {table = null;entrySet = null;keySet = null;values = null;modCount = 0;threshold = 0;size = 0;}// Callbacks to allow LinkedHashMap post-actions允许LinkedHashMap后动作的回调void afterNodeAccess(Node<K, V> p) {}void afterNodeInsertion(boolean evict) {}void afterNodeRemoval(Node<K, V> p) {}//仅从writeObject调用,以确保兼容顺序。void internalWriteEntries(java.io.ObjectOutputStream s) throws IOException {Node<K, V>[] tab;if (size > 0 && (tab = table) != null) {for (int i = 0; i < tab.length; ++i) {for (Node<K, V> e = tab[i]; e != null; e = e.next) {s.writeObject(e.key);s.writeObject(e.value);}}}}/* ------------------------------------------------------------ */// Tree bins/*** 进入树箱。LinkedHashMap延伸。入口(依次* 扩展节点)所以可以作为扩展的常规或* 链接节点。*/static final class TreeNode<K, V> extends LinkedHashMap.Entry<K, V> {TreeNode<K, V> parent;  // red-black tree linksTreeNode<K, V> left;TreeNode<K, V> right;TreeNode<K, V> prev;    // needed to unlink next upon deletion需要取消链接后删除boolean red;TreeNode(int hash, K key, V val, Node<K, V> next) {super(hash, key, val, next);}/*** Returns root of tree containing this node.返回包含此节点的树的根。*/final TreeNode<K, V> root() {for (TreeNode<K, V> r = this, p; ; ) {if ((p = r.parent) == null)return r;r = p;}}/*** Ensures that the given root is the first node of its bin.* 确保给定根是其bin的第一个节点。*/static <K, V> void moveRootToFront(Node<K, V>[] tab, TreeNode<K, V> root) {int n;if (root != null && tab != null && (n = tab.length) > 0) {int index = (n - 1) & root.hash;TreeNode<K, V> first = (TreeNode<K, V>) tab[index];if (root != first) {Node<K, V> rn;tab[index] = root;TreeNode<K, V> rp = root.prev;if ((rn = root.next) != null)((TreeNode<K, V>) rn).prev = rp;if (rp != null)rp.next = rn;if (first != null)first.prev = root;root.next = first;root.prev = null;}assert checkInvariants(root);}}/*** 使用给定的散列和键查找从根p开始的节点。* kc参数在第一次使用时缓存comparableClassFor(key)* 比较键。* /* final TreeNode<K,V> find(int h, Object k, Class<?> kc) {* TreeNode<K,V> p = this;* do {* int ph, dir; K pk;* TreeNode<K,V> pl = p.left, pr = p.right, q;* if ((ph = p.hash) > h)* p = pl;* else if (ph < h)* p = pr;* else if ((pk = p.key) == k || (k != null && k.equals(pk)))* return p;* else if (pl == null)* p = pr;* else if (pr == null)* p = pl;* else if ((kc != null ||* (kc = comparableClassFor(k)) != null) &&* (dir = compareComparables(kc, k, pk)) != 0)* p = (dir < 0) ? pl : pr;* else if ((q = pr.find(h, k, kc)) != null)* return q;* else* p = pl;* } while (p != null);* return null;* }* <p>* /*** Calls find for root node.调用查找根节点。*/final TreeNode<K, V> getTreeNode(int h, Object k) {return ((parent != null) ? root() : this).find(h, k, null);}//      /
//              *领带打破实用程序订购插入时,平等
//* hashCodes和non-comparable。我们不需要总数
//*顺序,只是一个一致的插入规则来维护
//*重新平衡的等价性。打破僵局的超过
//        必要的简化测试。
//                * /static int tieBreakOrder(Object a, Object b) {int d;if (a == null || b == null ||(d = a.getClass().getName().compareTo(b.getClass().getName())) == 0)d = (System.identityHashCode(a) <= System.identityHashCode(b) ?-1 : 1);return d;}/*** 构成从该节点链接的节点的树。** @返回树的根*/final void treeify(Node<K, V>[] tab) {TreeNode<K, V> root = null;for (TreeNode<K, V> x = this, next; x != null; x = next) {next = (TreeNode<K, V>) x.next;x.left = x.right = null;if (root == null) {x.parent = null;x.red = false;root = x;} else {K k = x.key;int h = x.hash;Class<?> kc = null;for (TreeNode<K, V> p = root; ; ) {int dir, ph;K pk = p.key;if ((ph = p.hash) > h)dir = -1;else if (ph < h)dir = 1;else if ((kc == null &&(kc = comparableClassFor(k)) == null) ||(dir = compareComparables(kc, k, pk)) == 0)dir = tieBreakOrder(k, pk);TreeNode<K, V> xp = p;if ((p = (dir <= 0) ? p.left : p.right) == null) {x.parent = xp;if (dir <= 0)xp.left = x;elsexp.right = x;root = balanceInsertion(root, x);break;}}}}moveRootToFront(tab, root);}/*** 返回非树节点的列表,以替换链接自的树节点* 此节点。*/final Node<K, V> untreeify(HashMap<K, V> map) {Node<K, V> hd = null, tl = null;for (Node<K, V> q = this; q != null; q = q.next) {Node<K, V> p = map.replacementNode(q, null);if (tl == null)hd = p;elsetl.next = p;tl = p;}return hd;}/*** Tree version of putVal.*/final TreeNode<K, V> putTreeVal(HashMap<K, V> map, Node<K, V>[] tab,int h, K k, V v) {Class<?> kc = null;boolean searched = false;TreeNode<K, V> root = (parent != null) ? root() : this;for (TreeNode<K, V> p = root; ; ) {int dir, ph;K pk;if ((ph = p.hash) > h)dir = -1;else if (ph < h)dir = 1;else if ((pk = p.key) == k || (k != null && k.equals(pk)))return p;else if ((kc == null &&(kc = comparableClassFor(k)) == null) ||(dir = compareComparables(kc, k, pk)) == 0) {if (!searched) {TreeNode<K, V> q, ch;searched = true;if (((ch = p.left) != null &&(q = ch.find(h, k, kc)) != null) ||((ch = p.right) != null &&(q = ch.find(h, k, kc)) != null))return q;}dir = tieBreakOrder(k, pk);}TreeNode<K, V> xp = p;if ((p = (dir <= 0) ? p.left : p.right) == null) {Node<K, V> xpn = xp.next;TreeNode<K, V> x = map.newTreeNode(h, k, v, xpn);if (dir <= 0)xp.left = x;elsexp.right = x;xp.next = x;x.parent = x.prev = xp;if (xpn != null)((TreeNode<K, V>) xpn).prev = x;moveRootToFront(tab, balanceInsertion(root, x));return null;}}}/*** 删除给定的节点,必须在此调用之前到场。* 这比典型的红黑删除代码更混乱* 不能用叶交换内部节点的内容* 被“下一个”指针固定的继任者* 在遍历期间独立。所以我们交换树* 联系。如果当前树的节点太少,* 箱子被转换回普通的箱子。(测试触发器* 在2到6个节点之间,取决于树结构。*/final void removeTreeNode(HashMap<K, V> map, Node<K, V>[] tab,boolean movable) {int n;if (tab == null || (n = tab.length) == 0)return;int index = (n - 1) & hash;TreeNode<K, V> first = (TreeNode<K, V>) tab[index], root = first, rl;TreeNode<K, V> succ = (TreeNode<K, V>) next, pred = prev;if (pred == null)tab[index] = first = succ;elsepred.next = succ;if (succ != null)succ.prev = pred;if (first == null)return;if (root.parent != null)root = root.root();if (root == null || root.right == null ||(rl = root.left) == null || rl.left == null) {tab[index] = first.untreeify(map);  // too smallreturn;}TreeNode<K, V> p = this, pl = left, pr = right, replacement;if (pl != null && pr != null) {TreeNode<K, V> s = pr, sl;while ((sl = s.left) != null) // find successors = sl;boolean c = s.red;s.red = p.red;p.red = c; // swap colorsTreeNode<K, V> sr = s.right;TreeNode<K, V> pp = p.parent;if (s == pr) { // p was s's direct parentp.parent = s;s.right = p;} else {TreeNode<K, V> sp = s.parent;if ((p.parent = sp) != null) {if (s == sp.left)sp.left = p;elsesp.right = p;}if ((s.right = pr) != null)pr.parent = s;}p.left = null;if ((p.right = sr) != null)sr.parent = p;if ((s.left = pl) != null)pl.parent = s;if ((s.parent = pp) == null)root = s;else if (p == pp.left)pp.left = s;elsepp.right = s;if (sr != null)replacement = sr;elsereplacement = p;} else if (pl != null)replacement = pl;else if (pr != null)replacement = pr;elsereplacement = p;if (replacement != p) {TreeNode<K, V> pp = replacement.parent = p.parent;if (pp == null)root = replacement;else if (p == pp.left)pp.left = replacement;elsepp.right = replacement;p.left = p.right = p.parent = null;}TreeNode<K, V> r = p.red ? root : balanceDeletion(root, replacement);if (replacement == p) {  // detachTreeNode<K, V> pp = p.parent;p.parent = null;if (pp != null) {if (p == pp.left)pp.left = null;else if (p == pp.right)pp.right = null;}}if (movable)moveRootToFront(tab, r);}/*** 将树状容器中的节点分成上下树状容器,* 如果现在太小,就不需要。仅从resize调用;* 参见上面关于分割位和索引的讨论。** @param映射地图* @param标签记录箱子头的表格* @param索引被分割的表的索引* @param是用来分割的散列*/final void split(HashMap<K, V> map, Node<K, V>[] tab, int index, int bit) {TreeNode<K, V> b = this;// Relink into lo and hi lists, preserving orderTreeNode<K, V> loHead = null, loTail = null;TreeNode<K, V> hiHead = null, hiTail = null;int lc = 0, hc = 0;for (TreeNode<K, V> e = b, next; e != null; e = next) {next = (TreeNode<K, V>) e.next;e.next = null;if ((e.hash & bit) == 0) {if ((e.prev = loTail) == null)loHead = e;elseloTail.next = e;loTail = e;++lc;} else {if ((e.prev = hiTail) == null)hiHead = e;elsehiTail.next = e;hiTail = e;++hc;}}if (loHead != null) {if (lc <= UNTREEIFY_THRESHOLD)tab[index] = loHead.untreeify(map);else {tab[index] = loHead;if (hiHead != null) // (else is already treeified)loHead.treeify(tab);}}if (hiHead != null) {if (hc <= UNTREEIFY_THRESHOLD)tab[index + bit] = hiHead.untreeify(map);else {tab[index + bit] = hiHead;if (loHead != null)hiHead.treeify(tab);}}}/* ------------------------------------------------------------ */// Red-black tree methods, all adapted from CLRstatic <K, V> TreeNode<K, V> rotateLeft(TreeNode<K, V> root,TreeNode<K, V> p) {TreeNode<K, V> r, pp, rl;if (p != null && (r = p.right) != null) {if ((rl = p.right = r.left) != null)rl.parent = p;if ((pp = r.parent = p.parent) == null)(root = r).red = false;else if (pp.left == p)pp.left = r;elsepp.right = r;r.left = p;p.parent = r;}return root;}static <K, V> TreeNode<K, V> rotateRight(TreeNode<K, V> root,TreeNode<K, V> p) {TreeNode<K, V> l, pp, lr;if (p != null && (l = p.left) != null) {if ((lr = p.left = l.right) != null)lr.parent = p;if ((pp = l.parent = p.parent) == null)(root = l).red = false;else if (pp.right == p)pp.right = l;elsepp.left = l;l.right = p;p.parent = l;}return root;}static <K, V> TreeNode<K, V> balanceInsertion(TreeNode<K, V> root,TreeNode<K, V> x) {x.red = true;for (TreeNode<K, V> xp, xpp, xppl, xppr; ; ) {if ((xp = x.parent) == null) {x.red = false;return x;} else if (!xp.red || (xpp = xp.parent) == null)return root;if (xp == (xppl = xpp.left)) {if ((xppr = xpp.right) != null && xppr.red) {xppr.red = false;xp.red = false;xpp.red = true;x = xpp;} else {if (x == xp.right) {root = rotateLeft(root, x = xp);xpp = (xp = x.parent) == null ? null : xp.parent;}if (xp != null) {xp.red = false;if (xpp != null) {xpp.red = true;root = rotateRight(root, xpp);}}}} else {if (xppl != null && xppl.red) {xppl.red = false;xp.red = false;xpp.red = true;x = xpp;} else {if (x == xp.left) {root = rotateRight(root, x = xp);xpp = (xp = x.parent) == null ? null : xp.parent;}if (xp != null) {xp.red = false;if (xpp != null) {xpp.red = true;root = rotateLeft(root, xpp);}}}}}}static <K, V> TreeNode<K, V> balanceDeletion(TreeNode<K, V> root,TreeNode<K, V> x) {for (TreeNode<K, V> xp, xpl, xpr; ; ) {if (x == null || x == root)return root;else if ((xp = x.parent) == null) {x.red = false;return x;} else if (x.red) {x.red = false;return root;} else if ((xpl = xp.left) == x) {if ((xpr = xp.right) != null && xpr.red) {xpr.red = false;xp.red = true;root = rotateLeft(root, xp);xpr = (xp = x.parent) == null ? null : xp.right;}if (xpr == null)x = xp;else {TreeNode<K, V> sl = xpr.left, sr = xpr.right;if ((sr == null || !sr.red) &&(sl == null || !sl.red)) {xpr.red = true;x = xp;} else {if (sr == null || !sr.red) {if (sl != null)sl.red = false;xpr.red = true;root = rotateRight(root, xpr);xpr = (xp = x.parent) == null ?null : xp.right;}if (xpr != null) {xpr.red = (xp == null) ? false : xp.red;if ((sr = xpr.right) != null)sr.red = false;}if (xp != null) {xp.red = false;root = rotateLeft(root, xp);}x = root;}}} else { // symmetricif (xpl != null && xpl.red) {xpl.red = false;xp.red = true;root = rotateRight(root, xp);xpl = (xp = x.parent) == null ? null : xp.left;}if (xpl == null)x = xp;else {TreeNode<K, V> sl = xpl.left, sr = xpl.right;if ((sl == null || !sl.red) &&(sr == null || !sr.red)) {xpl.red = true;x = xp;} else {if (sl == null || !sl.red) {if (sr != null)sr.red = false;xpl.red = true;root = rotateLeft(root, xpl);xpl = (xp = x.parent) == null ?null : xp.left;}if (xpl != null) {xpl.red = (xp == null) ? false : xp.red;if ((sl = xpl.left) != null)sl.red = false;}if (xp != null) {xp.red = false;root = rotateRight(root, xp);}x = root;}}}}}/*** Recursive invariant check递归不变量检查*/static <K, V> boolean checkInvariants(TreeNode<K, V> t) {TreeNode<K, V> tp = t.parent, tl = t.left, tr = t.right,tb = t.prev, tn = (TreeNode<K, V>) t.next;if (tb != null && tb.next != t)return false;if (tn != null && tn.prev != t)return false;if (tp != null && t != tp.left && t != tp.right)return false;if (tl != null && (tl.parent != t || tl.hash > t.hash))return false;if (tr != null && (tr.parent != t || tr.hash < t.hash))return false;if (t.red && tl != null && tl.red && tr != null && tr.red)return false;if (tl != null && !checkInvariants(tl))return false;if (tr != null && !checkInvariants(tr))return false;return true;}}}

HashMap源码注释翻译相关推荐

  1. IntelliJ IDEA生产力工具 -- 源码注释翻译神器

    IntelliJ IDEA生产力工具 – 源码注释翻译神器 本次给大家分享的IntelliJ IDEA提效插件是Translation. 用IDEA看源码时,难免会遇到有不认知的英文单词或翻译不通的句 ...

  2. Java Comparator源码总结 Comparator源码注释翻译和解析中英文对照版

    版本 JDK8(JDK1.8) Comparator接口重点 1.Comparator接口是一个函数式接口,里面只有一个虚方法compare(T o1, T o2),该接口表示一个比较器,而实现Com ...

  3. Java ReentrantLock源码总结 ReentrantLock源码注释翻译和解析中英文对照版 AQS虚拟类的实现

    文章目录 ReentrantLock类源码重点 具体实现 lock操作 acquire操作 tryAcquire操作 公平锁版本 非公平锁版本 lockInterruptibly操作 acquireI ...

  4. Netty源码注释翻译-Channel类

    定义为一个通往网络socket或者一个由I/O读写能力的组件. 通道提供: 1,通道的当前状态,打开?已连接? 2,跟通道关联的配置信息ChannelConfig,包括buffer大小等. 3,通道支 ...

  5. Qt之语言家的简单使用(一)(Qt翻译UI,Qt Linguist的使用,含源码+注释)

    文章目录 一.翻译程序示例图 二.流程须知(个人理解) 三.关于对话框中QDialogButtonBox翻译的操作 四.源码 CLinguistTest.h CLinguistTest.cpp CLi ...

  6. Java源码详解二:HashMap源码分析--openjdk java 11源码

    文章目录 HashMap.java介绍 1.HashMap的get和put操作平均时间复杂度和最坏时间复杂度 2.为什么链表长度超过8才转换为红黑树 3.红黑树中的节点如何排序 本系列是Java详解, ...

  7. hashmap为什么用红黑树_要看HashMap源码,先来看看它的设计思想

    HashMap 是日常开发中,用的最多的集合类之一,也是面试中经常被问到的 Java 类之一.同时,HashMap 在实现方式上面又有十分典型的范例.不管是从哪一方面来看,学习 HashMap 都可以 ...

  8. hashmap containsvalue时间复杂度_不看看HashMap源码,怎么和面试官谈薪资

    HashMap 是日常开发中,用的最多的集合类之一,也是面试中经常被问到的 Java 类之一.同时,HashMap 在实现方式上面又有十分典型的范例.不管是从哪一方面来看,学习 HashMap 都可以 ...

  9. 面试官系统精讲Java源码及大厂真题 - 08 HashMap 源码解析

    08 HashMap 源码解析 自信和希望是青年的特权. --大仲马 引导语 HashMap 源码很长,面试的问题也非常多,但这些面试问题,基本都是从源码中衍生出来的,所以我们只需要弄清楚其底层实现原 ...

最新文章

  1. Java基础-流程控制
  2. Linux 网卡驱动 PHY Mac MDIO kernel 驱动讲解 (未完待续)
  3. eosjs 文档(介绍)
  4. 根据当前时间如何找到上月的第一天和最后一天?
  5. python 实现HMAC_SHA1算法
  6. linux java usb 串口_2019-11-02 Linux下USB-串口的使用
  7. python循环输入字符串_Python基础-条件判断、循环、字符串格式化
  8. mysql5.6 load_MySQL 5.6 dump/load buffer pool实验
  9. VScode设置console.log('')快捷键
  10. 浅谈长尾理论--《Makers》读后感
  11. 用计算机弹让我做你的眼睛,童珺 - 让我做你的眼睛 (改编版)-酷歌词...
  12. 5分钟商学院学习笔记
  13. 高等数学关于切线,法线,切平面,法平面的详细解释
  14. win7无法连接打印机拒绝访问_win7添加打印机提示windows无法连接到打印机怎么解决...
  15. java游戏少年张三丰的原代码_RPG大作《少年张三丰》完美游戏攻略
  16. 各种符号的英文读法读音单词
  17. 东北师范大学计算机信息技术学院,东北师范大学计算机科学与信息技术学院2015年硕士研究生招生专业目录...
  18. #define s(x) x*x 的计算方法
  19. JNLP 文件无法打开的解决办法
  20. java对象转json格式化_Java对象转json JsonFormat注解

热门文章

  1. 牢房问题 C++(寻找总因子数为奇数的数)
  2. 百度云存储教程---免费建立自己的静态站点
  3. Kali linux下图片隐写,图片隐写信息快速检测工具——zsteg
  4. eclipse/myeclipse安装svn和maven配置
  5. UI设计-软件产品设计
  6. 赋能城市应急系统,推动智慧城市加速落地
  7. 小程序毕业设计 汽车维修保养预约小程序毕设作品开题报告参考
  8. ReentrantLock加锁与释放锁分享
  9. 自然语言处理基础(4)--数据平滑技术
  10. Templates在setting中设置所在目录