【java基础】hashmap

前言

hash
任何字符都有一个hash值,一个对象的hash值是唯一确定的
例如查看a的hash值可以使用a.hashcode()来打印a的原始hash值
但是原始hash值并不能作为hashmap的key,还需要一定的算法也就是hash函数来对值进行转换,转换为二次hash值也就是本hashmap所使用的作为key的hash值。
注意:hash值的算法有很多例如希尔与取余还有数字分析法,直接定址法,平方取中法这里我们讨论的是常见的除留余数法。
下面是1.8的hashmap的二次hash
在这里插入图片描述
二次hash会使数据更加均匀分布于桶中。

hashmap

长啥样?
在这里插入图片描述

扩容

factor是装填因子,是map扩容的依据。上图放第13个数据触发扩容
hashmap的扩容是成倍扩容
16 32 64

hashmap的优势是可以通过《计算hash函数》这一步骤避免盲目顺序查找

jdk8红黑树

避免链化过长,于是树化。
树化阈值为8且数组长度不小于64。
长啥样?
在这里插入图片描述
左小右大,其实就是折半查找的判定树,相同颜色的节点还要满足平衡树的条件。
当我们删除元素时可能需要调整平衡性
这些都是为了能够更加高效的查找。

红黑树的缺点是treenode更加占空间了

红黑树退化成链表

第一种情况是正对扩容的情况导致的退化
第二种退化情况是针对移除元素时的操作要在移除前判断
在这里插入图片描述

为什么重写equals要重写hashcode?

总结:放入时三步比较。1.hash值 2 .equals 3.二次hash
下面的hashset可以换为hashmap
当你把对象加入 HashSet 时,HashSet 会先计算对象的 hashCode 值来判断对象加入的位置,同时也会与其他已经加入的对象的 hashCode 值作比较,如果没有相符的 hashCode,HashSet 会假设对象没有重复出现。但是如果发现有相同 hashCode 值的对象,这时会调用 equals() 方法来检查 hashCode 相等的对象是否真的相同。如果两者相同,HashSet 就《不会让其加入操作成功》。如果不同的话,就会重新散列到其他位置。。这样我们就大大减少了 equals 的次数,相应就大大提高了执行速度。 其实, hashCode() 和 equals()都是用于比较两个对象是否相等。
注意点:
1.要知道hashcode方便我们进行查找操作进而去比较。
2.要知道上述过程的顺序:先比较hash值,不一样在比较equals,还不一样说明两者完全不同那就会发生二次散列。

那为什么两个对象有相同的 hashCode 值,它们也不一定是相等的?
因为 hashCode() 所使用的哈希算法也许刚好会让多个对象传回相同的哈希值。越糟糕的哈希算法越容易碰撞,但这也与数据值域分布的特性有关(所谓哈希碰撞也就是指的是不同的对象得到相同的 hashCode )。 总结下来就是 :
如果两个对象的hashCode 值相等,那这两个对象不一定相等(哈希碰撞)。
如果两个对象的hashCode 值相等并且equals()方法返回 true,我们才认为这两个对象相等。
如果两个对象的hashCode 值不相等,我们就可以直接认为这两个对象不相等。

重写 equals() 时没有重写 hashCode() 方法的话就可能会导致 equals 方法判断是相等的两个对象,hashCode 值却不相等。这样hashset当中就会重复加入equals的对象了。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值