说明
Map 接口的基于哈希表的实现。此实现提供了所有可选的映射操作,并允许 null 值和 null 键。 (HashMap 类大致等同于 Hashtable,除了它是非同步的并且允许空值。)该类不保证映射的顺序;特别是,它不保证订单会随着时间的推移保持不变。
此实现为基本操作(get 和 put)提供恒定时间性能,假设散列函数将元素正确地分散到存储桶中。集合视图上的迭代需要的时间与 HashMap 实例的“容量”(桶的数量)加上它的大小(键值映射的数量)成正比。因此,如果迭代性能很重要,则不要将初始容量设置得太高(或负载因子太低),这一点非常重要。
HashMap 的实例有两个影响其性能的参数:initial capacity 和 load factor。 容量是哈希表中的桶数,初始容量只是哈希表创建时的容量。 负载因子 是衡量哈希表在其容量自动增加之前允许达到多满的指标。当哈希表中的条目数超过负载因子和当前容量的乘积时,对哈希表进行重新哈希(即重新构建内部数据结构),这样哈希表大约有两倍桶的数量。
作为一般规则,默认负载因子 (0.75) 在时间和空间成本之间提供了很好的权衡。较高的值会减少空间开销,但会增加查找成本(反映在 HashMap 类的大多数操作中,包括 get 和 put)。在设置其初始容量时,应考虑映射中的预期条目数及其负载因子,以尽量减少重新哈希操作的次数。如果初始容量大于最大条目数除以负载因子,则不会发生重新哈希操作。
如果许多映射要存储在一个 HashMap 实例中,创建一个足够大的容量将允许映射更有效地存储,而不是让它根据需要执行自动重新散列来增加表。请注意,使用具有相同 hashCode() 的多个键是降低任何哈希表性能的可靠方法。为了改善影响,当键是 Comparable 时,此类可以使用键之间的比较顺序来帮助打破联系。
注意这个实现不是同步的。如果多个线程同时访问一个哈希映射,并且至少有一个线程在结构上修改了映射,它必须在外部同步。 (结构修改是添加或删除一个或多个映射的任何操作;仅更改与实例已包含的键关联的值不是结构修改。)这通常是通过同步一些自然封装映射的对象来完成的.如果不存在此类对象,则应使用 CollectionssynchronizedMap Collections.synchronizedMap 方法“包装”地图。这最好在创建时完成,以防止对地图的意外不同步访问: Map m = Collections.synchronizedMap(new HashMap(...));
所有此类返回的迭代器“集合视图方法”是fail-fast:如果在迭代器创建后的任何时间以任何方式修改地图结构,除了通过迭代器自己的remove 方法,迭代器将抛出一个 ConcurrentModificationException。因此,面对并发修改,迭代器快速而干净地失败,而不是在未来不确定的时间冒着任意、非确定性行为的风险。
请注意,无法保证迭代器的快速失败行为,因为一般来说,在存在非同步并发修改的情况下不可能做出任何硬性保证。快速失败的迭代器会尽最大努力抛出 ConcurrentModificationException。因此,编写一个依赖此异常来确保其正确性的程序是错误的:迭代器的快速失败行为应该仅用于检测错误。
源码说明(仅部分代码)
/**
* 默认的初始容量,必须是2的幂指数
*/
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
/**
* 最大容量,在两个带参数的构造函数隐式指定更高值时使用。必须是 2 的幂 <= 1<<30。
*/
static final int MAXIMUM_CAPACITY = 1 << 30;
/**
* 默认的负载因子,大小为0.75
*/
static final float DEFAULT_LOAD_FACTOR = 0.75f;
/**
* 使用树而不是列表的 bin 计数阈值。将元素添加到至少具有这么多节点的 bin 时,bin 会转换为树。该值必须大于 2 且至少应为 8,以与树移除中关于在收缩时转换回普通 bin 的假设相匹配。(就是小于8的时候,采用链表,大于等于8时采用树结构)
*/
static final int TREEIFY_THRESHOLD = 8;
/**
* 在调整大小操作期间取消(拆分)bin 的 bin 计数阈值。应小于 TREEIFY_THRESHOLD,最多为 6 以在移除下进行收缩检测。
*/
static final int UNTREEIFY_THRESHOLD = 6;
/**
* 可以将 bin 树化的最小表容量。 (否则,如果 bin 中的节点过多,则表将调整大小。)应至少为 4 TREEIFY_THRESHOLD,以避免调整大小和树化阈值之间发生冲突。
*/
static final int MIN_TREEIFY_CAPACITY = 64;
/**
* 节点说明,hash值和key值是final修饰的
*/
static class Node<K,V> implements Map.Entry<K,V> {
final int hash;
final K key;
V value;
Node<K,<