HashMap

本文详细介绍了HashMap在Java中的实现,包括哈希值计算、存储结构(数组+链表/红黑树)、冲突解决策略以及JDK1.7和1.8版本的优化。重点讨论了链表转红黑树和红黑树转链表的阈值设定及其背后的逻辑。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

HashMap是Java中常用的实现了Map接口的哈希表数据结构。它基于哈希算法实现,提供了高效的插入、删除和查找操作。HashMap以键值对(key-value)的形式存储数据,其中键是唯一的,值可以重复。

HashMap存储数据的原理大致是:

  • 计算哈希值:对键对象调用其hashCode()方法来获取哈希值。hashCode()方法是Object类的方法,可以被所有Java对象继承和覆盖。哈希值是一个整数,用于表示键的唯一标识。
  • 确定索引位置:使用哈希值和当前数组的长度进行计算,以确定键值对应该放置在数组的哪个索引位置。通常,这是通过对哈希值进行模运算(取余操作)来实现的。具体计算方式为:索引位置 = 哈希值 % 数组长度。
  • 哈希冲突:如果发生了哈希冲突,即不同的键对象计算得到相同的哈希值,那么它们将会被放置在同一个索引位置上,以形成一个链表或树的数据结构。

详细流程如下:

  1. 首先根据 key 的值计算 hash 值,找到该元素在数组中存储的下标;
  2. 如果数组是空的,则调用 resize 进行初始化;
  3. 如果没有哈希冲突直接放在对应的数组下标里;
  4. 如果冲突了,且 key 已经存在,就覆盖掉 value;
  5. 如果冲突后,发现该节点是红黑树,就将这个节点挂在树上;
  6. 如果冲突后是链表,判断该链表是否大于 8 ,如果大于 8 并且数组容量小于 64,就进行扩容;如果链表节点大于 8 并且数组的容量大于 64,则将这个结构转换为红黑树;否则,链表插入键值对,若 key 存在,就覆盖掉 value。

 

常用的方法

V get(Object key)根据键获取对应的值
V put(K key, V value) 将指定的键值对添加到HashMap中
V remove(Object key)根据键移除对应的键值对,并返回被移除的值
boolean containsKey(Object key)判断HashMap中是否包含指定的键
boolean containsValue(Object value)判断HashMap中是否包含指定的值
int size()返回HashMap中键值对的数量
boolean isEmpty() 判断HashMap是否为空
void clear()清空HashMap,移除所有的键值对
Collection<V> values()返回HashMap中所有值的集合(Collection)
Set<Map.Entry<K, V>> entrySet()回HashMap中所有键值对的集合(Set)
Set<K> keySet()返回HashMap中所有键的集合(Set)

存储结构:

1.7版本:

在JDK1.7 中,由“数组+链表”组成,数组是 HashMap 的主体,链表则是主要为了解决哈希冲突而存在的。

1.8之后

在JDK1.8 中,由“数组+链表+红黑树”组成。当链表过长,则会严重影响 HashMap 的性能,红黑树搜索时间复杂度是 O(logn),而链表是O(n)。因此,JDK1.8 对数据结构做了进一步的优化,引入了红黑树,链表和红黑树在达到一定条件会进行转换。

  • 当链表超过 8 且数据总量超过 64 才会转红黑树。
  • 将链表转换成红黑树前会判断,如果当前数组的长度小于 64,那么会选择先进行数组扩容,而不是转换为红黑树,以减少搜索时间。

为什么链表转红黑树的阈值是8?

hash碰撞发生8次的概率已经降低到了0.00000006,几乎为不可能事件,如果真的碰撞发生了8次,那么这个时候说明由于元素本身和hash函数的原因,此时的链表性能已经已经很差了,操作的hash碰撞的可能性非常大了,后序可能还会继续发生hash碰撞。

为什么红黑树转链表的阈值是6?

如果设计成链表个数超过8则链表转换成树结构,链表个数小于8则树结构转换成链表,如果HashMap不停的插入,删除元素,链表个数在8左右徘徊,就会频繁的发生红黑树转链表,链表转红黑树,效率会很低下。

为什么在解决 hash 冲突的时候,不直接用红黑树?而选择先用链表,再转红黑树?

因为红黑树需要进行左旋,右旋,变色这些操作来保持平衡,而单链表不需要。当元素小于 8 个的时候,此时做查询操作,链表结构已经能保证查询性能。当元素大于 8 个的时候, 红黑树搜索时间复杂度是 O(logn),而链表是 O(n),此时需要红黑树来加快查询速度,但是新增节点的效率变慢了。

因此,如果一开始就用红黑树结构,元素太少,新增效率又比较慢,无疑这是浪费性能的。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值