hashMap基础知识总结

HashMap是一种基于哈希表的数据结构,由数组加链表组成。它利用哈希桶解决哈希碰撞,数组中的链表越短,性能越好。在JDK7中,碰撞节点过多时查询时间为O(n),JDK8引入红黑树降低查询时间至O(nlogn)。HashMap在负载因子超过0.75时自动扩容,同时,重写equals方法时必须重写hashCode,以确保散列正确。由于HashMap非线程安全,多线程环境下推荐使用ConcurrentHashMap。

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

1. hashmap是由数组加链表组成的,数组是hashmap的哈希桶,链表是为解决哈希碰撞而存在的,如果定位到的数组位置不含链表(即哈希桶中只有一个entry),则对于查找、添加等操作很快在,只有O(1),只需要一次寻址即可(数组根据下标寻址),如果定位到的数组包含链表,对于添加操作,其时间复杂度为O(n),首先遍历链表,存在即覆盖,否则新增。对于查找操作来讲,也需要遍历链表,然后通过key对象的equals方法逐一比较查找。所以,就性能考虑,hashmap中的链表越少,则性能越好。即,哈希表的hash值越离散,entry就会尽可能均匀的分布,出现链表的概率就越低。

2. hashMap不会将元素放在链表的尾部,而是放在头部,这是为了避免尾部遍历。

3. hashMap有两个有参构造器可以用来设置initialCapacity和loadFactor的值,即HashMap的初始容量和负载因子的值,如果不传则使用默认值。

4. 在jdk7中,hashMap处理碰撞问题时,都是采用链表来存储,当碰撞的节点很多时,查询的时间是O(n)。

在jdk8中,hashMap处理碰撞问题增加了红黑树这种数据结构,当碰撞节点较少(<8)时,采用链表存储,当碰撞节点较大(>8)时,则采用红黑树(特点是查询时间为O(nlogn))存储。 工作:前面产生冲突的那些key对应的记录只是简单的追加到链表的头部,这些记录只能用遍历来查找,但是超过了阈值后,hashmap开始将列表升级为一个二叉树,使用hash值作为树的分支变量。如果两个hash值不等,但指向同一个桶的话,较大的那个会插到右子树中。若hash值相等,hashMap希望key值最好是实现了comparable接口,这样就可以按照顺序来进行插入。如果没有实现这个接口,则性能提升就很难实现。

为什么一开始不使用红黑树?→因为红黑树维护比较困难。

5. 红黑树的扩容:hashMap中的数组(哈希桶)默认初始长度为16,但是当数组中有数据的个数超过总数的0.75时,hashMap就会自动扩容。

6. 如果对象会用hashMap/hashSet/hashTable等构成对象的集合时,如果重写equals方法必定要重写hashcode方法。

原因:equals和hashcode都是java的基类Object类的方法。equals方法是用于比较两个值是否相等,hashcode主要作用是为了配合基于散列的集合一起正常运行,这样的散列集合包括hashset、hashMap、hashTable。 如果补充些hashcode方法,则对相同内容的两个对象的hash值不同,会导定位到hashMap的不同哈希桶中,因此不会get到值。

7.hashMap的并发问题:

hashMap不能在并发场景下使用,因为在hashMap的源码中,它的所有方法都没有同步处理,实际上只要是在堆中的对象,如果在多线程情况下使用而不做同步处理的话,都有可能导致数据不一致的问题。

hashMap的哈希桶中的数据正常情况下是单向链表,而jdk1.7中的hashMap在并发情况下有可能形成环形链表。环形链表的产生是在扩容阶段产生的。

在jdk1.8中修复了产生环形链表的问题,即使用两个局部链表进行扩容不会出现哈希环。但是jdk1.8中的hashMap仍然不能在并发场景下使用,因为hashMap的put方法在并发下会出现丢数据的问题。

对于hashMap的并发问题,有以下解决方案:

①使用hashTable,hashTable是线程安全的。但HashTable源码好像只是在方法上加上了synchronize方法,而synchronize 属于重量级锁,对效率损耗是比较大的。

② 使用jdk1.8中的ConcurrentHashMap,这个类实现了更高级的线程安全,且使用分段锁,在并发下也可有很高的吞吐量,推荐使用。、

 

参考链接:

https://blog.csdn.net/tuke_tuke/article/details/51588156

https://lushunjian.github.io/blog/2019/01/02/HashMap%E7%9A%84%E5%BA%95%E5%B1%82%E5%AE%9E%E7%8E%B0/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值