⭐️前面的话⭐️
HashMap 是 Java 集合框架中 Map 容器的一个实现类,用于存储键值对(key - value)。在 JDK 7 中,其底层采用数组 + 链表实现;在 JDK 8 中,采用数组 + 链表 + 红黑树实现。所有的 key 构成一个 Set 集合,key 无序且不能重复,同时 HashMap 支持存储 key/value 为 null
的元素。
📒博客主页:未见花闻的博客主页
🎉欢迎关注🔎点赞👍收藏⭐️留言📝
📌本文由未见花闻原创,CSDN首发!
📆首发时间:🌴2025年5月5日🌴
✉️坚持和努力一定能换来诗与远方!
💭推荐书籍:📚《无》
💬参考在线编程网站:🌐牛客网🌐力扣🌐acwing
博主的码云gitee,平常博主写的程序代码都在里面。
博主的github,平常博主写的程序代码都在里面。
🍭作者水平很有限,如果发现错误,一定要及时告知作者哦!感谢感谢!
一、知识点讲解
1.1 HashMap 基本概念
HashMap 是 Java 集合框架中 Map 容器的一个实现类,用于存储键值对(key - value)。在 JDK 7 中,其底层采用数组 + 链表实现;在 JDK 8 中,采用数组 + 链表 + 红黑树实现。所有的 key 构成一个 Set 集合,key 无序且不能重复,同时 HashMap 支持存储 key/value 为 null
的元素。
1.2 HashMap 的属性
- 默认容量:
DEFAULT_INITIAL_CAPACITY = 1 << 4
,即 16,且必须是 2 的幂。 - 最大容量:
MAXIMUM_CAPACITY = 1 << 30
,即 2 30 2^{30} 230。 - 默认负载因子:
DEFAULT_LOAD_FACTOR = 0.75f
。 - 链表树化阈值:
TREEIFY_THRESHOLD = 8
,当数组长度大于 64 且链表长度超过 8 时,链表转换为红黑树。 - 红黑树链表化阈值:
UNTREEIFY_THRESHOLD = 6
,当红黑树结点个数小于 6 时,红黑树转换为链表。 - 底层数组:
transient Node<K,V>[] table
,是一个链表数组。 - 元素个数阈值:
threshold = capacity * loadFactor
,当size
大于threshold
时会执行resize
操作。
1.3 HashMap 的构造方法
- 无参构造方法:默认容量为 16,但此时不会申请数组空间。
public HashMap() {
this.loadFactor = DEFAULT_LOAD_FACTOR;
}
- 指定容量的构造方法:取大于或等于指定容量的最接近的 2 次幂数,同样不立即申请数组空间。
public HashMap(int initialCapacity) {
this(initialCapacity, DEFAULT_LOAD_FACTOR);
}
- 指定容量和负载因子的构造方法:
tableSizeFor(initialCapacity)
生成比initialCapacity
大并最接近的 2 次幂。
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);
}
- 根据其他 Map 对象构造:若传入的参数有元素,则申请数组空间,否则不申请。
public HashMap(Map<? extends K, ? extends V> m) {
this.loadFactor = DEFAULT_LOAD_FACTOR;
putMapEntries(m, false);
}
1.4 HashMap 开辟数组的时机
真正为数组分配内存是在第一次 put
操作时。
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
1.5 HashMap 中的 put 操作
- 首次扩容:若数组为空,则进行第一次扩容(
resize
),申请默认容量大小为 16 的数组。 - 插入数据步骤:
- 通过
hash()
方法计算索引,找到键值对在数组中的位置。 - 插入数据:
- 若当前位置元素为空,直接插入。
- 若当前位置元素非空,遍历链表或红黑树,若 key 已存在,则覆盖其 value。
- 若当前位置元素非空,遍历链表或红黑树,若 ke
- 通过