1.HashMap是什么
先简单介绍一下Java的集合框架概念,Java的集合框架可以动态的存放多个数据,以及提供一系列的操作API,用于更好的操作程序中的数据,而HashMap就是Java中的集合框架之一。
2.HashMap的应用场景
(1).HashMap是一个散列表,主要用于存储具有key-value特征的数据。
(2).HashMap能够以较低的时间复杂度快速查找到指定的键对应的数据项。
3.HashMap的原理
3.1 HashMap的继承关系
HashMap是基于哈希表对Map接口的实现,继承关系如图所示:

HashMap提供所有可选的映射操作(key-value的一系列操作),允许有null的key和null的value。值得注意的是,HashMap不保证键值对的顺序(即遍历出来的键值对顺序很大可能与添加顺序不一致)。
3.2 HashMap的底层数据结构
HashMap采用了数组+链表+红黑树(JDK8),这里红黑树是对JDK7版本HashMap的优化,用于解决hash冲突过多情况下,链表长度过大,导致查询效率过低问题。(链表的查询效率为O(n),红黑树的查询效率为O(logn))。结构如下:

存储键值对过程的重要三个部分:
(1)哈希桶:
当创建HashMap集合对象时,在JDK8版本以前,构造方法默认会创建一个长度为16的Entry[] table数组来存储键值对数据。(这里Entry就是键值对类,table就是键值对数组对象,Entry[]就是对应上图的哈希桶)。而在JDK8后则采用了懒加载的思想,即第一次调用put方法的时候才会真正创建数组Node[] table(这里Node只是换了名字,本质和Entry没有很大的区别,都是实现了Map.Entry<K,V>接口)来存储键值对 。
(2)链表:
当发生Hash冲突时,即不同的键被Hash函数映射在了哈希桶的同一个位置,这个时候,HashMap采用的是拉链法来处理Hash冲突,即在原位置的基础上创建一个链表节点,将新的键值对放入该链表节点中。
(3)红黑树:
红黑树是JDK8引入的数据结构,目的是为了解决链表查询慢的问题,当链表长度大于8且哈希桶的长度大于64时,则会将链表转换为红黑树。
一个键值对添加流程:
(1)调用key的hashCode方法计算出对应的hash值-->通过哈希算法将hash值转换成哈希桶下标
(2)该位置上如果没有任何元素,则直接将该键值对添加到这个位置上。
(3)如果有,则调用equals方法确认是否是相同的key,如果是,则将新的Value值覆盖旧的Value值,不是,则遍历该位置上的链表或者红黑树上的节点的key是否相等,如果是,则将新的Value值覆盖旧的Value值,如果都不是,则是一个新的键值对,则添加到链表末尾或者添加在红黑树上。
3.3 HashMap的一些主要属性:
(1)loadFactor 称为负载因子,默认值为0.75.负载因子是用来衡量HashMap键值对疏密程度的,hash桶越密,发生hash冲突的概率越大,哈希桶越稀疏,空间利用率越低。所以loadFactor属性就是稀疏程度的一个属性。而0.75则是官方给出的比较好的一个默认值。
默认情况下:当hash桶中的元素数量占总长度的75%时,代表元素过密了,发生hash冲突的概率会很大,这个时候会触发扩容机制,扩充hash桶的长度。

(2)threshold标识链表转换为红黑树的阈值,当链表长度大于8且哈希桶的长度大于64时才会转换成红黑树(这里简要解释一下为什么是8,这个是经过复杂的概率统计计算出来的结果,即链表长度大于8发生的概率很小,除非键值对真的非常多,即设置成8要进行树化的情况概率很小).

(3)size是HashMap中真实存在的键值对数量

(4) modCount字段用来记录HashMap内部结构发生变化的次数
(5)initialCapacity初始默认容量(哈希桶)大小为16,(如果使用的是无参构造器)

3.4 HashMap的扩容机制
触发时机:当HashMap中的键值对个数超过了(哈希桶数量*loadFactor)时,就会触发数组扩容。
扩容方法:哈希桶数量扩大一倍,即容量翻倍,然后重新计算每个元素的位置(这其实是一个非常消耗性能的操作,如果能够预先知道数据量,可以通过预先分配容量的方式有效提高HashMap的性能)
每次扩容容量翻倍的原因:这是为了提高重新计算元素位置函数的效率,如果容量扩大为原来的一倍,则原集合中的键值在进行重新hash散列的时候与原来((n - 1) & hash)计算结果相比,只是多了一位,那么重新进行hash散列的结果要么是原来的位置,要么就是“原来的位置+原来的容量”。
HashMap是Java集合框架中的重要组成部分,它基于哈希表实现,提供了key-value的存储和快速查找。HashMap适用于需要快速查找和存储键值对的场景。其内部采用数组+链表+红黑树的数据结构,通过负载因子和扩容机制平衡空间利用率和性能。当冲突过多时,链表会转为红黑树,以保持高效查询。主要属性包括负载因子、阈值、容量和已存储键值对数量。

1万+

被折叠的 条评论
为什么被折叠?



