HashMap相关

一、HashMap的预备知识

1.HashMap是Map的常用子类java.util.HashMap<k,v> 集合 implements Map<k,v>接口

2.HashMap集合特点HashMap集合底层是哈希表,查询速度特别快 jdk1.7:数组+单向链表 jdk1.8:数组+单向链表/红黑树(链表长度超过8,数组达到64)

3.HashMap集合是一个无序的集合,存储元素和取出元素的顺序有可能不一致

二、HashMap的底层实现原理

数组:查询速度快,可以根据索引查询;但插入和删除比较困难

链表:查询速度慢,需要遍历整个链表,但插入和删除操作比较容易。

HashMap底层是一个hash表(数组+链表),这种结构集合了数组和链表的好处 。

jdk1.7中,只是单纯的数组+链表的结构,但是如果散列表中的hash碰撞过多时,会造成效率的降低,所以在JKD1.8中对这种情况进行了控制,当一个hash值上的链表长度大于8时,该节点上的数据就不再以链表进行存储,而是转成了一个红黑树

HashMap 基于 Hash 算法实现的

当我们往Hashmap中put元素时,利用key的hashCode重新hash计算出当前对象的元素在数组中的下标存储时,如果出现hash值相同的key,此时有两种情况。

(1)如果key相同,则覆盖原始值;

(2)如果key不同(出现冲突),则将当前的key-value放入链表中获取时,直接找到hash值对应的下标,在进一步判断key是否相同,从而找到对应值。

理解了以上过程就不难明白HashMap是如何解决hash冲突的问题,核心就是使用了数组的存储方式,然后将冲突的key的对象放入链表中,一旦发现冲突就在链表中做进一步的对比。

三、HashMap的1.7和1.8

JDK1.7JDK1.7采用的是拉链法。拉链法:将链表和数组相结合。也就是说创建一个链表数组,数组中每一格就是一个链表。若遇到哈希冲突,则将冲突的值加到链表中即可。

JDK1.8相比于之前的版本,jdk1.8在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为8)同时数组长度达到64,将链表转化为红黑树,以减少搜索时间。(红黑树节点为6时转回链表)

四、JDK1.8主要对HashMap进行了一系列优化

resize 扩容优化

引入了红黑树,目的是避免单条链表过长而影响查询效率

解决了多线程死循环问题,但仍是非线程安全的,多线程时可能会造成数据丢失问题。

五、HashMap的put与get
put方法
key的hashcode经过高低位异或后的值,然后(table.length - 1) & hash得到槽位下标

此时有四种情况
当槽位(slot)为空,key和value包装为一个node对象,直接存储占用一个slot
槽位不为空,判断key是否一样,一样则进行value替换;否则为hash冲突,存入链表中
已经链化,和2过程相同,比较存入链表但是会判断是否达到了树化的扩容阈值标准
红黑树的写入操作

get方法拿到key算出对应索引
5. 根据得到的索引,映射到对应的哈希桶,判断该元素是不是头结点,如果是则直接拿到
6. 如果不是头一个节点,用do while循环遍历链表,链表都是next指向一次拿元素
7. 如果是红黑树,由于添加时保证树有序,则利用折半法遍历红黑树

在使用 HashMap 的时候,用 String 做 key 有什么好处?

HashMap 内部实现是通过 key 的 hashcode 来确定 value 的存储位置,因为字符串是不可变的,所以当创建字符串时,它的 hashcode 被缓存下来,不需要再次计算,所以相比于其他对象更快。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值