本站消息

站长简介/公众号

  出租广告位,需要合作请联系站长


+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

暂无数据

各种数据类型的哈希值hashCode的实现原理以及源码分析

发布于2021-05-29 20:27     阅读(1196)     评论(0)     点赞(16)     收藏(2)


前言

规定HashCode的值的数据类型一定要是整型(int),这应该是我们公认的常识。
所以在计算不同类型数据的HashCode时,我们只需要将其转换成int类型即可,而且要尽量避免重复。

一、基本数据类型的HashCode的实现原理以及计算

1、int类型

(1)分析

我们将int类型本省的数据作为HashCode就可以,符合HashCode的条件。
为了更具有说服力,我们来看一下java(JDK1.8)官方的处理方式。

(2)源码

在这里插入图片描述
在这里插入图片描述

2、float类型

(1)分析

我们知道float是由32位二进制组成,int也是由32位二进制组成,所以我们只需要将float的二进制数转成int类型就OK了。下面我们来看一下源码

(2)源码

在这里插入图片描述
在这里插入图片描述

第三张图就是将float的二进制转化成int的原理。
比如:10.5对应的HashCode是1093140480
在这里插入图片描述

3、long类型

(1)分析

对于long而言,其是由64位二进制数组成,求long类型HashCode的解决方案是将long类型的“高32位”与“低32位”进行“亦或(^)”运算,然后取运算结果的“低32位”。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
最后将其转化成整型就OK了。

线面我们来看看源码:

(2)源码

在这里插入图片描述
在这里插入图片描述
是不是完全符合我上面分子的

4、double类型

(1)分析

对于double而言,会将其二进制先转成long类型的二进制,然后再将long类型转成int(方法同上)。
我们直接看源码吧

(2)源码

在这里插入图片描述
在这里插入图片描述

5、boolean类型

(1)分析

对于Boolean类型其实是最简单的,因为Boolean类型就只有true和false两种,那么我们只需要认为规定两个数字作为其HashCode就可以。

(2)源码

我们来看一下java官方给Boolean类型规定的两个数字是什么
在这里插入图片描述
在这里插入图片描述

二、String类的HashCode的实现原理以及计算

(1)分析

对于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”。很明显位运算要比乘运算高效的多。

(2)手动实现

在这里插入图片描述
在这里插入图片描述

(3)源码分析

在这里插入图片描述
在这里插入图片描述

三、自定义类的HashCode的实现原理以及计算

(1)源码

在每一个类中创建时,是默认实现了hashCode()方法的
我们来看一下java官方是怎么实现的
在这里插入图片描述
是不是很懵逼,我也很懵逼,既然使用了native,那么说明就算是和地址相关的。

(2)需求分析

我们可能会有这么一种需求,对于不同的对象,只要它的内部的属性值相同,那么我们人民这两个对象是相同的,但是很显然java提供的hashCode()是不满足我们的需求的,看下图:
在这里插入图片描述

(3)解决个性化需求

既然java的hashCode()不给力,那么我们就只能进行重写了,但是问题是我们应该一怎么一个策略进行编写。

经过分析不难发现,对象中的所有属性我们可以认为其组成了一个“字符串”,我们可以通过计算字符串的hashCode的方法宏观的计算“属性字符串”的hashCode,因为类的属性都是又上述的几种数据类型组成,所以对于各个属性单独的hashCode,我们可以直接调用其相应的hashCode

重写hashCode():
在这里插入图片描述
执行结果:
在这里插入图片描述

(4)如果其他类作为属性时怎么处理

其实这个问题很简单,分为两方面

  1. 如果对弈类属性,类属性的属性值相同则认为类属性相同,那么该类也需要重写hashCode().
  2. 如果认为类属性的地址相同,类属性才相同,那么不需要重写hashCode

处理上述的两个条件外,其他的处理和普通的属性的处理方式相同。

五、怎么通过key的哈希值映射到value的存放索引

我们上面已经知道了获取一个数据类型的哈希值,下一步是怎么通过获取到的哈希值映射到value存放的索引。

通过哈希值映射到其对应的索引(map的索引映射原理)【点击查看】

在这里插入图片描述



所属网站分类: 技术文章 > 博客

作者:快起来搬砖啦

链接:http://www.javaheidong.com/blog/article/207364/51ce38f0967494b30d3f/

来源:java黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

16 0
收藏该文
已收藏

评论内容:(最多支持255个字符)