发布于2021-05-29 20:27 阅读(1196) 评论(0) 点赞(16) 收藏(2)
规定HashCode的值的数据类型一定要是整型(int),这应该是我们公认的常识。
所以在计算不同类型数据的HashCode时,我们只需要将其转换成int类型即可,而且要尽量避免重复。
我们将int类型本省的数据作为HashCode就可以,符合HashCode的条件。
为了更具有说服力,我们来看一下java(JDK1.8)官方的处理方式。
我们知道float是由32位二进制组成,int也是由32位二进制组成,所以我们只需要将float的二进制数转成int类型就OK了。下面我们来看一下源码
第三张图就是将float的二进制转化成int的原理。
比如:10.5对应的HashCode是1093140480
对于long而言,其是由64位二进制数组成,求long类型HashCode的解决方案是将long类型的“高32位”与“低32位”进行“亦或(^)”运算,然后取运算结果的“低32位”。
最后将其转化成整型就OK了。
线面我们来看看源码:
是不是完全符合我上面分子的
对于double而言,会将其二进制先转成long类型的二进制,然后再将long类型转成int(方法同上)。
我们直接看源码吧
对于Boolean类型其实是最简单的,因为Boolean类型就只有true和false两种,那么我们只需要认为规定两个数字作为其HashCode就可以。
我们来看一下java官方给Boolean类型规定的两个数字是什么
对于String类型而言,其实是可以类比进制计算的方式来规定,我们举一个例子:
对于12345这么一个整数,其实就是(1*10^4) + (2 * 10^3) +(3 *10^2) + (2 * 10^1) +(1 * 10^0)
那么对于“abcd”而言,我们是到‘a’本身即是可以用ascall码【点击查看】,那么我们是不是可以类比上面的计算:
“abcd” = (a * n^3) +(b *n^2) + (c * n^1) +(d * n^0)
怎么解决啥你那的问题呢?看下图
解决了重复计算的问题,先一步是确定n为多少合适。我们应该选用31作为n,因为31是一个奇素数,JVM会将“31 * i”优化成“(i<<5)- i”。很明显位运算要比乘运算高效的多。
在每一个类中创建时,是默认实现了hashCode()方法的
我们来看一下java官方是怎么实现的
是不是很懵逼,我也很懵逼,既然使用了native,那么说明就算是和地址相关的。
我们可能会有这么一种需求,对于不同的对象,只要它的内部的属性值相同,那么我们人民这两个对象是相同的,但是很显然java提供的hashCode()是不满足我们的需求的,看下图:
既然java的hashCode()不给力,那么我们就只能进行重写了,但是问题是我们应该一怎么一个策略进行编写。
经过分析不难发现,对象中的所有属性我们可以认为其组成了一个“字符串”,我们可以通过计算字符串的hashCode的方法宏观的计算“属性字符串”的hashCode,因为类的属性都是又上述的几种数据类型组成,所以对于各个属性单独的hashCode,我们可以直接调用其相应的hashCode。
重写hashCode():
执行结果:
其实这个问题很简单,分为两方面
处理上述的两个条件外,其他的处理和普通的属性的处理方式相同。
我们上面已经知道了获取一个数据类型的哈希值,下一步是怎么通过获取到的哈希值映射到value存放的索引。
通过哈希值映射到其对应的索引(map的索引映射原理)【点击查看】
作者:快起来搬砖啦
链接:http://www.javaheidong.com/blog/article/207364/51ce38f0967494b30d3f/
来源:java黑洞网
任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任
昵称:
评论内容:(最多支持255个字符)
---无人问津也好,技不如人也罢,你都要试着安静下来,去做自己该做的事,而不是让内心的烦躁、焦虑,坏掉你本来就不多的热情和定力
Copyright © 2018-2021 java黑洞网 All Rights Reserved 版权所有,并保留所有权利。京ICP备18063182号-2
投诉与举报,广告合作请联系vgs_info@163.com或QQ3083709327
免责声明:网站文章均由用户上传,仅供读者学习交流使用,禁止用做商业用途。若文章涉及色情,反动,侵权等违法信息,请向我们举报,一经核实我们会立即删除!